From c028b49f99338d93bb6cd86b0b4b5f42828dfb76 Mon Sep 17 00:00:00 2001 From: aiongg Date: Sat, 24 Oct 2026 01:23:26 +0000 Subject: [PATCH] Batch fix: EPS: executable names count against the PostScript call depth --- crates/pdf/src/ps.rs | 12 +++++++++++- crates/pdf/src/tests_import.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/pdf/src/ps.rs b/crates/pdf/src/ps.rs index 88385186..e8612e42 100644 --- a/crates/pdf/src/ps.rs +++ b/crates/pdf/src/ps.rs @@ -454,7 +454,17 @@ impl Interp { self.calls -= 1; r } - V::Name(n) => self.exec_name(&n, src), + // An executable name can run another (`exec` of `/exec cvx`), so names count too. + V::Name(n) => { + if self.calls >= MAX_CALL_DEPTH { + self.b.skip("PostScript (recursion limit)"); + return Err(Flow::Quit); + } + self.calls += 1; + let r = self.exec_name(&n, src); + self.calls -= 1; + r + } other => { self.push(other); Ok(()) diff --git a/crates/pdf/src/tests_import.rs b/crates/pdf/src/tests_import.rs index 71b93a78..ca5e2417 100644 --- a/crates/pdf/src/tests_import.rs +++ b/crates/pdf/src/tests_import.rs @@ -55,6 +55,14 @@ fn eps_filter_on_a_string_source_does_not_skip_the_program() { assert!(coverage(&render(&doc), 50, 25, 150, 75) > 4900.0, "drawing after an image read from a string"); } +/// Each `exec` of the executable name `exec` runs the next one: the chain is cut off at the call +/// depth instead of overflowing the stack. +#[test] +fn eps_exec_of_executable_names_stops_at_the_call_depth() { + let doc = parse(b"%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 200 100\n/exec cvx 99999 {dup} repeat exec\n").unwrap(); + assert!(doc.skipped.iter().any(|s| s.contains("recursion limit")), "{:?}", doc.skipped); +} + #[test] fn eps_text_with_bundled_fonts_and_show_variants() { // Not embedded: drawn with the bundled stand-in, like the same text in a PDF.