diff options
| author | Micha White <botahamec@outlook.com> | 2023-02-13 00:53:32 -0500 |
|---|---|---|
| committer | Micha White <botahamec@outlook.com> | 2023-02-13 00:53:32 -0500 |
| commit | 38008d6a84457afad717e4524adcf963305fb0b7 (patch) | |
| tree | c0196bf816f04d10d8ab1843fa33b67fb14d8ab6 /tvg | |
| parent | 89aa6df441d806d6b3d32bc87cf34daf418cf06d (diff) | |
check for non-zero padding
Diffstat (limited to 'tvg')
| -rw-r--r-- | tvg/src/lib.rs | 16 | ||||
| -rw-r--r-- | tvg/src/path.rs | 54 |
2 files changed, 49 insertions, 21 deletions
diff --git a/tvg/src/lib.rs b/tvg/src/lib.rs index 3b585d7..6b07ff0 100644 --- a/tvg/src/lib.rs +++ b/tvg/src/lib.rs @@ -77,19 +77,21 @@ impl<C: Color + std::fmt::Debug> TvgFile<C> { pub enum TvgError { #[error("Not a valid TVG file. The magic number was invalid.")] InvalidFile, - #[error("Expected version 1, but found version {}", .0)] + #[error("Expected version 1, but found version {}.", .0)] UnsupportedVersion(u8), - #[error("Found a coordinate range with an index of 3, which is invalid")] + #[error("Found a coordinate range with an index of 3, which is invalid.")] InvalidCoordinateRange, - #[error("Found a Custom color encoding, which is unsupported")] + #[error("Found a Custom color encoding, which is unsupported.")] UnsupportedColorEncoding, - #[error("Found a command with an index of {}, which is invalid", .0)] + #[error("Found a command with an index of {}, which is invalid.", .0)] InvalidCommand(u8), - #[error("Found a style kind with an index of 3, which is invalid")] + #[error("Found a style kind with an index of 3, which is invalid.")] InvalidStyleKind, - #[error("Polygons must have at least 3 points, found {}", .0)] + #[error("Polygons must have at least 3 points, found {}.", .0)] InvalidPolygon(u32), - #[error("The end of the document must have a `prim_style_kind` value of 0. Found {}", .0)] + #[error("All padding bits must be zero. Found {}.", .0)] + NonZeroPadding(u8), + #[error("The end of the document must have a `prim_style_kind` value of 0. Found {}.", .0)] InvalidEndOfDocument(u8), #[error("{}", .0)] IoError(#[from] io::Error), diff --git a/tvg/src/path.rs b/tvg/src/path.rs index d2bf4fb..2bc0448 100644 --- a/tvg/src/path.rs +++ b/tvg/src/path.rs @@ -1,9 +1,19 @@ -use std::io::{self, Read}; +use std::io::Read; use byteorder::ReadBytesExt; use num_enum::TryFromPrimitive; +use raise::yeet; -use crate::{header::TvgHeader, read_unit, read_varuint, Decode, Point}; +use crate::{header::TvgHeader, read_unit, read_varuint, Decode, Point, TvgError}; + +/// Returns an error if the padding isn't zero +fn check_padding(padding: u8) -> Result<(), TvgError> { + if padding != 0 { + yeet!(TvgError::NonZeroPadding(padding)) + } + + Ok(()) +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)] #[repr(u8)] @@ -122,7 +132,11 @@ enum InstructionData { } impl InstructionData { - fn read(reader: &mut impl Read, header: &TvgHeader, kind: InstructionKind) -> io::Result<Self> { + fn read( + reader: &mut impl Read, + header: &TvgHeader, + kind: InstructionKind, + ) -> Result<Self, TvgError> { match kind { InstructionKind::Line => Self::read_line(reader, header), InstructionKind::HorizontalLine => Self::read_horizontal_line(reader, header), @@ -135,25 +149,25 @@ impl InstructionData { } } - fn read_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { Ok(Self::Line { position: Point::read(reader, header)?, }) } - fn read_horizontal_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_horizontal_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { Ok(Self::HorizontalLine { x: read_unit(reader, header)?, }) } - fn read_vertical_line(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_vertical_line(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { Ok(Self::VerticalLine { y: read_unit(reader, header)?, }) } - fn read_cubic_bezier(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_cubic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { Ok(Self::CubicBezier { control_0: Point::read(reader, header)?, control_1: Point::read(reader, header)?, @@ -161,7 +175,10 @@ impl InstructionData { }) } - fn read_arc_header(reader: &mut impl Read, header: &TvgHeader) -> io::Result<(bool, Sweep)> { + fn read_arc_header( + reader: &mut impl Read, + header: &TvgHeader, + ) -> Result<(bool, Sweep), TvgError> { // large_arc and sweep are stored in the same byte let byte = reader.read_u8()?; let large_arc = (byte & 1) != 0; @@ -170,10 +187,12 @@ impl InstructionData { _ => Sweep::Right, }; + check_padding((byte & 0b1111_1100) >> 2)?; + Ok((large_arc, sweep)) } - fn read_arc_circle(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_arc_circle(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { let (large_arc, sweep) = Self::read_arc_header(reader, header)?; let radius = read_unit(reader, header)?; let target = Point::read(reader, header)?; @@ -186,7 +205,7 @@ impl InstructionData { }) } - fn read_arc_ellipse(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_arc_ellipse(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { let (large_arc, sweep) = Self::read_arc_header(reader, header)?; let radius_x = read_unit(reader, header)?; let radius_y = read_unit(reader, header)?; @@ -203,7 +222,7 @@ impl InstructionData { }) } - fn read_quadratic_bezier(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read_quadratic_bezier(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { Ok(Self::QuadraticBezier { control: Point::read(reader, header)?, target: Point::read(reader, header)?, @@ -220,12 +239,15 @@ struct Instruction { } impl Instruction { - fn read(reader: &mut impl Read, header: &TvgHeader) -> io::Result<Self> { + fn read(reader: &mut impl Read, header: &TvgHeader) -> Result<Self, TvgError> { let byte = reader.read_u8()?; let instruction_kind = InstructionKind::try_from_primitive(byte & 0b0000_0111).expect("invalid instruction"); let has_line_width = (byte & 0b0001_0000) != 0; + check_padding((byte & 0b0000_1000) >> 3)?; + check_padding((byte & 0b1110_0000) >> 5)?; + let line_width = has_line_width .then(|| read_unit(reader, header)) .transpose()?; @@ -244,7 +266,11 @@ struct Segment { } impl Segment { - fn read(reader: &mut impl Read, header: &TvgHeader, segment_length: u32) -> io::Result<Self> { + fn read( + reader: &mut impl Read, + header: &TvgHeader, + segment_length: u32, + ) -> Result<Self, TvgError> { let start = Point::read(reader, header)?; let mut instructions = Vec::with_capacity(segment_length as usize); @@ -276,7 +302,7 @@ impl Path { reader: &mut impl Read, header: &TvgHeader, segment_count: u32, - ) -> io::Result<Self> { + ) -> Result<Self, TvgError> { let mut segment_lengths = Vec::with_capacity(segment_count as usize); for _ in 0..segment_count { segment_lengths.push(read_varuint(reader)? + 1); |
