mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-11 21:32:39 +00:00
Refuse encoding unverified glyphs after a font decode allowance refusal
This commit is contained in:
1 parent
ef7f2f3116
commit
6f5f361368
2 files changed
+30
-1
No files matched your search
@@ -979,8 +979,14 @@ impl Metrics {
|
||||
}
|
||||
|
||||
/// The bytes that show `text` in this font, or `None` if some character has no code or
|
||||
/// no glyph in it (the caller then substitutes another font).
|
||||
/// no glyph in it, or the metrics were read past their allowance (the caller then substitutes
|
||||
/// another font). Empty text needs no verified glyph and always encodes.
|
||||
pub fn encode(&self, text: &str) -> Option<Vec<u8>> {
|
||||
// A refused read cannot establish the mappings or glyphs needed to write new text.
|
||||
// Empty text needs neither and remains usable for erasing existing text.
|
||||
if self.past_allowance && !text.is_empty() {
|
||||
return None;
|
||||
}
|
||||
// The lowest code showing each wanted character. Explicit entries and the encoding are
|
||||
// checked one by one; each range is asked for the wanted characters it can show.
|
||||
let wanted: HashSet<char> = text.chars().collect();
|
||||
|
||||
@@ -1173,3 +1173,26 @@ fn low_codes_resolve_to_the_covering_range() {
|
||||
assert_eq!(covered, [5, 6, 7, 100, 101]);
|
||||
assert_eq!((u.covering(0xFFFF).is_some(), u.covering(0x1_0001).is_some(), u.covering(0x1_0002).is_none()), (true, true, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refused_subset_reads_do_not_encode_unverified_glyphs() {
|
||||
let mut doc = Document::new_empty();
|
||||
let (mut f, sizes) = subset_type0(&mut doc, b"");
|
||||
f.set(b"Encoding".to_vec(), Object::name("Identity-H"));
|
||||
f.set(b"ToUnicode".to_vec(), Object::name("Identity-H"));
|
||||
if let Some(Object::Array(descendants)) = f.get_mut(b"DescendantFonts")
|
||||
&& let Some(Object::Dict(descendant)) = descendants.first_mut()
|
||||
{
|
||||
descendant.set(b"DW".to_vec(), Object::Int(1000));
|
||||
}
|
||||
let whole = Metrics::from_dict(&doc, &f);
|
||||
assert!(!whole.past_allowance && !whole.outlined_cids.is_empty());
|
||||
assert!(whole.encode("\u{ffff}").is_none());
|
||||
// Refuse the program, then the CID map after reading the complete program.
|
||||
for allowance in [0, sizes[1]] {
|
||||
let partial = Metrics::from_dict_within(&doc, &f, &mut DecodeBudget::new(allowance, 0));
|
||||
assert!(partial.past_allowance);
|
||||
assert_eq!(partial.encode(""), Some(Vec::new()));
|
||||
assert!(partial.encode("\u{ffff}").is_none(), "allowance {allowance} must not turn /DW into proof of a glyph");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user