diff --git a/crates/eps/src/import/ai/read/ops.rs b/crates/eps/src/import/ai/read/ops.rs index de12631eb..2fda3dec1 100644 --- a/crates/eps/src/import/ai/read/ops.rs +++ b/crates/eps/src/import/ai/read/ops.rs @@ -82,6 +82,14 @@ impl<'a> Reader<'a> { // highlight `-- -- angle length Bh`): a NaN keeps the other operands where they are. "--" => return self.push(V::Num(f64::NAN)), "[" => { + // Drop marks that operators have taken off, so `marks` is the open nesting. + while self.marks.last().is_some_and(|&m| !matches!(self.stack.get(m), Some(V::Mark))) { + self.marks.pop(); + } + // Arrays nest as deep as their `[`s; dropping a deeper one would overflow the stack. + if self.marks.len() >= MAX_DEPTH { + return Err("it has arrays nested too deeply".into()); + } self.marks.push(self.stack.len()); return self.push(V::Mark); } diff --git a/crates/eps/src/import/ai/tests.rs b/crates/eps/src/import/ai/tests.rs index 6b1e8622d..52248aa1b 100644 --- a/crates/eps/src/import/ai/tests.rs +++ b/crates/eps/src/import/ai/tests.rs @@ -54,6 +54,14 @@ fn ruler_units_from_the_header_set_the_documents_units() { assert_eq!(read(with_px.as_bytes()).unwrap().doc.units, Unit::Pixels); } +#[test] +fn arrays_nested_past_the_depth_limit_are_refused() { + let deep = |n: usize| layer(&format!("{}{} pop", "[".repeat(n), "]".repeat(n))); + let nested = |n: usize| read(stream(&deep(n)).as_bytes()).err().is_some_and(|e| e.contains("nested too deeply")); + assert!(!nested(200)); + assert!(nested(100_000)); +} + /// The children of the first layer. fn art(doc: &Document) -> Vec> { doc.layers.first().and_then(|l| l.children()).cloned().unwrap_or_default()