mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-08 08:20:13 +00:00
Fix #5342: eexec skips in the file it is given
`eexec` dropped its file operand and skipped the encrypted part of a font program to `cleartomark` in the program's own file. With `currentfile eexec` inside a file run with `cvx exec`, the program goes on in that file, so the skip searched the outer file instead and failed or skipped the wrong text. Ghostscript's eps2write runs each embedded Type 1 font program that way, so an EPS with one did not open. `eexec` now skips in its operand, through the same file reading as the other data operators: the program's own file or the file being run. A string operand skips in the file being read, as before.
This commit is contained in:
@@ -435,10 +435,11 @@ impl Interp<'_> {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// `eexec`: an encrypted font program follows. It is skipped (type is drawn in the app's
|
||||
/// fonts, by name): the font dictionary it would complete is defined as it is.
|
||||
/// `file eexec`: an encrypted font program follows in `file`. It is skipped there, up to the
|
||||
/// `cleartomark` that ends it (type is drawn in the app's fonts, by name): the font
|
||||
/// dictionary it would complete is defined as it is.
|
||||
fn eexec(&mut self) -> Res {
|
||||
self.pop()?;
|
||||
let src = self.pop()?;
|
||||
if let Some(Obj::Dict(d)) = self.stack.last().cloned() {
|
||||
let name = d.borrow().get(&Key::name("FontName")).cloned();
|
||||
if let Some(k) = name.and_then(|n| n.key()) {
|
||||
@@ -446,9 +447,24 @@ impl Interp<'_> {
|
||||
self.fonts.borrow_mut().insert(k, Obj::Dict(d));
|
||||
}
|
||||
}
|
||||
let rest = self.lex.data();
|
||||
let at = find(rest, b"cleartomark").ok_or(PsError::Ps("ioerror", "eexec".into()))?;
|
||||
self.lex.advance(at);
|
||||
// `currentfile eexec`: the program's own file or the file being run. A string operand
|
||||
// skips in the file being read.
|
||||
let f = match src {
|
||||
Obj::File { stream, .. } => stream,
|
||||
_ => self.running.last().cloned().unwrap_or_else(|| Rc::new(RefCell::new(Stream::Current))),
|
||||
};
|
||||
self.materialize(&f)?;
|
||||
let missing = || PsError::Ps("ioerror", "eexec".into());
|
||||
match &mut *f.borrow_mut() {
|
||||
Stream::Buf { data, pos, .. } => {
|
||||
let at = find(data.get(*pos..).unwrap_or_default(), b"cleartomark").ok_or_else(missing)?;
|
||||
*pos += at;
|
||||
}
|
||||
_ => {
|
||||
let at = find(self.lex.data(), b"cleartomark").ok_or_else(missing)?;
|
||||
self.lex.advance(at);
|
||||
}
|
||||
}
|
||||
self.push(Obj::Mark)
|
||||
}
|
||||
|
||||
|
||||
@@ -717,14 +717,20 @@ fn type_42_fonts_set_type_at_their_size() {
|
||||
}
|
||||
}
|
||||
|
||||
/// The encrypted part of a font program is skipped up to its `cleartomark` in the file it is in:
|
||||
/// the program's own file, or a file being run (`cvx exec`), as Ghostscript's `eps2write` runs
|
||||
/// each Type 1 font it embeds.
|
||||
#[test]
|
||||
fn embedded_font_programs_are_skipped() {
|
||||
let body = "/MyFont 10 dict begin /FontName /MyFont def /FontMatrix [0.001 0 0 0.001 0 0] def currentdict end currentfile eexec\n\
|
||||
0123456789abcdef garbage that is encrypted\n0000000000000000000000000000000000000000000000000000000000000000\ncleartomark\n\
|
||||
/MyFont findfont 10 scalefont setfont 10 10 moveto (x) show";
|
||||
let r = read(body);
|
||||
let NodeKind::Text(t) = &objects(&r.document)[0].kind else { panic!("{:?}", r.warnings) };
|
||||
assert_eq!(t.runs[0].style.font_family, "My Font");
|
||||
for program in [body.to_string(), format!("currentfile 0 (endstream) /SubFileDecode filter cvx exec\n{body}\nendstream\n")] {
|
||||
let r = read(&program);
|
||||
let NodeKind::Text(t) = &objects(&r.document)[0].kind else { panic!("{program}: {:?}", r.warnings) };
|
||||
assert_eq!(t.runs[0].style.font_family, "My Font");
|
||||
assert!(r.warnings.is_empty(), "{program}: {:?}", r.warnings);
|
||||
}
|
||||
}
|
||||
|
||||
/// A document with what the writer writes in its own ways: gradients, type, an image with
|
||||
|
||||
Reference in New Issue
Block a user