Never crash: SVG path data no longer loops forever on a number after Z
Path data like "M0 0 L10 0 Z9" repeated Z implicitly for the stray number; Z consumes no numbers, so the parser looped forever appending close-paths until memory ran out (a 1-byte change to a valid SVG used 24 GB and was killed). A number after Z is a syntax error, so parsing now stops there and keeps what was read, as the spec asks. Also denies the panic lints in the crate (it had no panic sites). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
10644a83aa
commit
6708ff55b4
|
|
@ -0,0 +1,4 @@
|
|||
allow-unwrap-in-tests = true
|
||||
allow-expect-in-tests = true
|
||||
allow-panic-in-tests = true
|
||||
allow-indexing-slicing-in-tests = true
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
//! ([`Doc`]): groups with transforms and opacity, and shapes with fills and strokes in their own
|
||||
//! user space. [`rasterize`] draws it at any scale; the engine converts it to shape layers.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
mod color;
|
||||
mod pathdata;
|
||||
mod raster;
|
||||
|
|
|
|||
|
|
@ -109,8 +109,9 @@ pub fn parse_path_data(d: &str) -> BezPath {
|
|||
let c = match l.command() {
|
||||
Some(c) => c,
|
||||
None => match cmd {
|
||||
// Implicit repeat (a moveto repeats as lineto).
|
||||
Some(c) if l.at_number() => match c {
|
||||
// Implicit repeat (a moveto repeats as lineto). Z takes no numbers, so a number
|
||||
// after it is an error: repeating Z would loop forever without consuming input.
|
||||
Some(c) if l.at_number() && !c.eq_ignore_ascii_case(&b'z') => match c {
|
||||
b'M' => b'L',
|
||||
b'm' => b'l',
|
||||
other => other,
|
||||
|
|
@ -284,6 +285,15 @@ mod tests {
|
|||
assert!(parse_path_data("").elements().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_after_close_stops_instead_of_looping() {
|
||||
// "Z9": Z was repeated implicitly without consuming the number, appending close-paths
|
||||
// until memory ran out.
|
||||
let p = parse_path_data("M0 0 L10 0 L10 10 Z9 C1 2 3 4 5 6");
|
||||
assert_eq!(p.elements().len(), 4);
|
||||
assert!(parse_path_data("M0 0 L10 0 z 9 9").elements().len() <= 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_lists() {
|
||||
assert_eq!(numbers("0 0,100 50"), vec![0.0, 0.0, 100.0, 50.0]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue