diff --git a/CHANGELOG.md b/CHANGELOG.md index 1808e8d..75b49c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Few panics that can be triggered by an invalid input. +- `.` was parsed as `0` by `Steam::parse_number`. Now it's an error. +- Endless loop when a ClosePath segment was followed by a number. ## [0.2.1] - 2017-02-01 ### Fixed diff --git a/src/path.rs b/src/path.rs index 6cdc59e..5fe7e3c 100644 --- a/src/path.rs +++ b/src/path.rs @@ -177,6 +177,11 @@ impl<'a> Tokenizer<'a> { // unwrap is safe, because we checked 'has_prev_cmd' let prev_cmd = self.prev_cmd.unwrap(); + // ClosePath can't be followed by a number + if prev_cmd == b'Z' || prev_cmd == b'z' { + data_error!(); + } + if prev_cmd == b'M' || prev_cmd == b'm' { // 'If a moveto is followed by multiple pairs of coordinates, the subsequent // pairs are treated as implicit lineto commands.' diff --git a/src/stream.rs b/src/stream.rs index 93cb3ea..e1ec3b1 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -816,6 +816,13 @@ impl<'a> Stream<'a> { let mut fraction: f64; if mant_size == 0 { + // check that input is not equal to '.', which is not a number(0) + if self.is_char_eq(b'.')? { + // back to start + self.pos = start; + return Err(Error::InvalidNumber(self.gen_error_pos())); + } + return Ok(0.0); } else { let mut frac1 = 0.0; diff --git a/src/svg.rs b/src/svg.rs index 6d0cb1b..9b89631 100644 --- a/src/svg.rs +++ b/src/svg.rs @@ -396,7 +396,6 @@ impl<'a> Tokenizer<'a> { // check that element has tag name if start_pos == self.stream.pos() { - // return Err(Error::ElementWithoutTagName(self.stream.gen_error_pos())); return Err(Error::InvalidSvgToken(self.stream.gen_error_pos())); } diff --git a/tests/path.rs b/tests/path.rs index f6ff367..eb0a014 100644 --- a/tests/path.rs +++ b/tests/path.rs @@ -221,3 +221,18 @@ test!(close_path_3, b"M10 20 L 30 40 Z Z Z", Segment { cmd: b'Z', data: SegmentData::ClosePath }, Segment { cmd: b'Z', data: SegmentData::ClosePath } ); + +// first token should be EndOfStream +test!(invalid_1, b"M\t.", ); + +#[test] +fn invalid_2() { + // ClosePath can't be followed by a number + let stream = Stream::new(b"M0 0 Z 2"); + let mut s = Tokenizer::new(stream); + assert_eq!(s.parse_next().unwrap(), + SegmentToken::Segment(Segment { cmd: b'M', data: SegmentData::MoveTo { x: 0.0, y: 0.0 } })); + assert_eq!(s.parse_next().unwrap(), + SegmentToken::Segment(Segment { cmd: b'Z', data: SegmentData::ClosePath })); + assert_eq!(s.parse_next().unwrap(), SegmentToken::EndOfStream); +} diff --git a/tests/stream.rs b/tests/stream.rs index 833626b..55d6db5 100644 --- a/tests/stream.rs +++ b/tests/stream.rs @@ -38,7 +38,6 @@ test_number!(number_19, b"1ex", 1.0); test_number!(number_20, b"1em", 1.0); test_number!(number_21, b"12345678901234567890", 12345678901234567000.0); test_number!(number_22, b"0.", 0.0); -test_number!(number_23, b".", 0.0); // TODO: probably wrong // --- @@ -52,12 +51,13 @@ macro_rules! test_number_err { ) } -test_number_err!(number_err_1, b"q", Error::InvalidNumber(ErrorPos::new(1,1))); -test_number_err!(number_err_2, b"", Error::InvalidNumber(ErrorPos::new(1,1))); -test_number_err!(number_err_3, b"-", Error::UnexpectedEndOfStream(ErrorPos::new(1,2))); -test_number_err!(number_err_4, b"+", Error::UnexpectedEndOfStream(ErrorPos::new(1,2))); -test_number_err!(number_err_5, b"-q", Error::InvalidNumber(ErrorPos::new(1,1))); -test_number_err!(number_err_6, b"1e1111", Error::InvalidNumber(ErrorPos::new(1,1))); +test_number_err!(number_err_1, b"q", Error::InvalidNumber(ErrorPos::new(1,1))); +test_number_err!(number_err_2, b"", Error::InvalidNumber(ErrorPos::new(1,1))); +test_number_err!(number_err_3, b"-", Error::UnexpectedEndOfStream(ErrorPos::new(1,2))); +test_number_err!(number_err_4, b"+", Error::UnexpectedEndOfStream(ErrorPos::new(1,2))); +test_number_err!(number_err_5, b"-q", Error::InvalidNumber(ErrorPos::new(1,1))); +test_number_err!(number_err_6, b"1e1111", Error::InvalidNumber(ErrorPos::new(1,1))); +test_number_err!(number_err_7, b".", Error::InvalidNumber(ErrorPos::new(1,1))); // ---