Integration: #3195 keep CMap entries read before a stream ends inside a block

A begin… block cut off at the end of the stream returned None through ? and discarded the whole map; it now ends the scan like any other unparseable tail. Test: stream_cut_off_inside_a_block_keeps_the_entries_before_it.
This commit is contained in:
aiongg
2026-10-22 01:48:30 +00:00
parent 84e091d9b3
commit 69c87d2f3e
2 changed files with 39 additions and 9 deletions
+7
View File
@@ -1117,6 +1117,13 @@ endbfchar
);
}
#[test]
fn stream_cut_off_inside_a_block_keeps_the_entries_before_it() {
let cmap = parse_with_preamble(b"1 beginbfchar <41> <0058>\n<42> <00");
assert_eq!(cmap.lookup_bf_string(0x41), Some(BfString::Char('X')));
assert_eq!(cmap.lookup_bf_string(0x42), None);
}
#[test]
fn truncated_stream_with_no_entries_reports_failure() {
// The tolerant parser keeps collected entries, but a stream that
+32 -9
View File
@@ -50,8 +50,10 @@ pub(crate) fn parse_inner<'a>(
let mut last_name: Option<Vec<u8>> = None;
// PdfCraft patch: track whether the scan was cut short. A CMap with an
// unparseable tail keeps the entries read so far instead of being
// discarded wholesale; one that yielded nothing still reports failure.
// unparseable tail, including one that ends inside a `begin…` block,
// keeps the entries read so far (the block parsers push into the shared
// lists as they go) instead of being discarded wholesale; one that
// yielded nothing still reports failure.
let mut truncated = false;
// PdfCraft patch: track a `usecmap` reference that could not be resolved
@@ -94,25 +96,46 @@ pub(crate) fn parse_inner<'a>(
} else {
match name.as_str() {
Some("begincodespacerange") => {
parse_codespace_range(&mut scanner, &mut _codespace_ranges, &mut ctx)?;
if parse_codespace_range(&mut scanner, &mut _codespace_ranges, &mut ctx).is_none() {
truncated = true;
break;
}
}
Some("begincidrange") => {
parse_range(&mut scanner, &mut ranges, &mut ctx, "endcidrange")?;
if parse_range(&mut scanner, &mut ranges, &mut ctx, "endcidrange").is_none() {
truncated = true;
break;
}
}
Some("begincidchar") => {
parse_char(&mut scanner, &mut ranges, &mut ctx, "endcidchar")?;
if parse_char(&mut scanner, &mut ranges, &mut ctx, "endcidchar").is_none() {
truncated = true;
break;
}
}
Some("beginnotdefrange") => {
parse_range(&mut scanner, &mut notdef_ranges, &mut ctx, "endnotdefrange")?;
if parse_range(&mut scanner, &mut notdef_ranges, &mut ctx, "endnotdefrange").is_none() {
truncated = true;
break;
}
}
Some("beginnotdefchar") => {
parse_char(&mut scanner, &mut notdef_ranges, &mut ctx, "endnotdefchar")?;
if parse_char(&mut scanner, &mut notdef_ranges, &mut ctx, "endnotdefchar").is_none() {
truncated = true;
break;
}
}
Some("beginbfchar") => {
parse_bf_char(&mut scanner, &mut bf_entries, &mut ctx)?;
if parse_bf_char(&mut scanner, &mut bf_entries, &mut ctx).is_none() {
truncated = true;
break;
}
}
Some("beginbfrange") => {
parse_bf_range(&mut scanner, &mut bf_entries, &mut ctx)?;
if parse_bf_range(&mut scanner, &mut bf_entries, &mut ctx).is_none() {
truncated = true;
break;
}
}
Some("usecmap") => {
// PdfCraft patch: an unresolvable or unparseable `usecmap`