M2.6: hayro-interpret patches from fuzzing: tiling-pattern nesting cap (stack overflow), CID width ranges clamped to 65535 (hang)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
24418ae3c5
commit
675b258e77
|
|
@ -7,7 +7,7 @@ the fix. Vendoring copyleft code is never allowed (plan/adr/0001).
|
|||
|
||||
| Crate | Version | Licence | Patches | Test |
|
||||
|---|---|---|---|---|
|
||||
| hayro-interpret | 0.7.0 | Apache-2.0 OR MIT | (1) select `/AP /N` appearance states via `/AS` (checkboxes, radios, stateful icons) and honour the NoView flag; (2) Type3 Unicode fallback to `/Encoding` glyph names, then printable ASCII; (3) `Type3Glyph::advance_width`; (4) `InterpreterSettings::ocg_overrides` for viewer layer toggles; (5) soft masks whose group lacks `/CS` were dropped (Chrome gradient text) | (1) `raster::tests::widget_appearance_states`; (2, 3) `xtask text-oracle` on corpus/pdfjs issue918; (4) `raster::tests::layer_override_hides_content`; (5) `raster::tests::soft_mask_without_group_colour_space_is_applied` |
|
||||
| hayro-interpret | 0.7.0 | Apache-2.0 OR MIT | (1) select `/AP /N` appearance states via `/AS` (checkboxes, radios, stateful icons) and honour the NoView flag; (2) Type3 Unicode fallback to `/Encoding` glyph names, then printable ASCII; (3) `Type3Glyph::advance_width`; (4) `InterpreterSettings::ocg_overrides` for viewer layer toggles; (5) soft masks whose group lacks `/CS` were dropped (Chrome gradient text); (6) tiling-pattern nesting cap `MAX_PATTERN_NESTING` (a self-referencing pattern overflowed the stack); (7) CID width ranges in `/W` and `/W2` clamped to `MAX_CID` (a `0 4294967295 w` range hung) | (1) `raster::tests::widget_appearance_states`; (2, 3) `xtask text-oracle` on corpus/pdfjs issue918; (4) `raster::tests::layer_override_hides_content`; (5) `raster::tests::soft_mask_without_group_colour_space_is_applied`; (6) `raster::tests::self_referencing_tiling_pattern_terminates`; (7) `raster::tests::huge_cid_width_ranges_terminate` |
|
||||
|
||||
| hayro | 0.7.1 | Apache-2.0 OR MIT | `RenderSettings::{x_offset, y_offset}` to render one tile of a large page | `raster::tests::tiles_match_full_render` |
|
||||
| hayro-syntax | 0.7.2 | Apache-2.0 OR MIT | Page-tree cycle guard in `resolve_pages` (visited set + depth cap): a `/Kids` loop among compressed objects overflowed the stack and aborted the process | `cos/tests/writer.rs::page_tree_loops_in_object_streams_do_not_crash_readers` |
|
||||
|
|
|
|||
|
|
@ -509,6 +509,9 @@ impl CidToGIdMap {
|
|||
}
|
||||
}
|
||||
|
||||
/// PrintCraft patch: the largest CID (ISO 32000-2 §9.7.2; CIDs are at most two bytes).
|
||||
const MAX_CID: u32 = 65_535;
|
||||
|
||||
fn read_widths(arr: &Array<'_>) -> Option<HashMap<u32, f32>> {
|
||||
let mut map = HashMap::new();
|
||||
let mut iter = arr.flex_iter();
|
||||
|
|
@ -516,11 +519,16 @@ fn read_widths(arr: &Array<'_>) -> Option<HashMap<u32, f32>> {
|
|||
loop {
|
||||
if let Some((mut first, range)) = iter.next::<(u32, Array<'_>)>() {
|
||||
for width in range.iter::<f32>() {
|
||||
if first > MAX_CID {
|
||||
break;
|
||||
}
|
||||
map.insert(first, width);
|
||||
first = first.checked_add(1)?;
|
||||
}
|
||||
} else if let Some((first, second, width)) = iter.next::<(u32, u32, f32)>() {
|
||||
for i in first..=second {
|
||||
// PrintCraft patch: CIDs stop at 65535. A corrupt range such as
|
||||
// `0 4294967295 500` inserted billions of entries (found by fuzzing).
|
||||
for i in first..=second.min(MAX_CID) {
|
||||
map.insert(i, width);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -546,7 +554,8 @@ fn read_widths2(arr: &Array<'_>) -> Option<HashMap<u32, [f32; 3]>> {
|
|||
first = first.checked_add(1)?;
|
||||
}
|
||||
} else if let Some((first, second, w, v1, v2)) = iter.next::<(u32, u32, f32, f32, f32)>() {
|
||||
for i in first..=second {
|
||||
// PrintCraft patch: as in `read_widths`.
|
||||
for i in first..=second.min(MAX_CID) {
|
||||
map.insert(i, [w, v1, v2]);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ use kurbo::{Affine, BezPath, Rect, Shape};
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
/// PrintCraft patch: maximum nesting of tiling patterns (and the forms around them).
|
||||
const MAX_PATTERN_NESTING: u32 = 16;
|
||||
/// A PDF pattern.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Pattern<'a> {
|
||||
|
|
@ -228,6 +231,13 @@ impl<'a> TilingPattern<'a> {
|
|||
initial_transform: Affine,
|
||||
is_stroke: bool,
|
||||
) -> Option<()> {
|
||||
// PrintCraft patch: a tiling pattern can paint itself (directly, or through resources it
|
||||
// inherits when its own are missing), which recursed until the stack overflowed. Bound
|
||||
// the nesting like XObjects do, tighter because every level rasterizes a tile.
|
||||
if self.nesting_depth > MAX_PATTERN_NESTING {
|
||||
warn!("tiling pattern nesting depth exceeded");
|
||||
return None;
|
||||
}
|
||||
let state = State::new(initial_transform);
|
||||
|
||||
let mut context = Context::new_with(
|
||||
|
|
|
|||
Loading…
Reference in New Issue