diff --git a/crates/forms/src/lib.rs b/crates/forms/src/lib.rs index 8ab308a19..4735474ef 100644 --- a/crates/forms/src/lib.rs +++ b/crates/forms/src/lib.rs @@ -715,8 +715,8 @@ fn walk( if let Some(ft) = d.name(b"FT") { inh.ft = Some(ft.to_vec()); } - if let Some(ff) = d.get(b"Ff").and_then(|o| doc.resolve(o).as_int()) { - inh.ff = Some(ff as u32); + if let Some(ff) = field_flags(doc, d) { + inh.ff = Some(ff); } for (k, slot) in [(&b"V"[..], &mut inh.v), (b"DV", &mut inh.dv)] { if let Some(v) = d.get(k) { @@ -812,6 +812,10 @@ fn walk( }); } +fn field_flags(doc: &Document, dict: &Dict) -> Option { + dict.get(b"Ff").and_then(|value| doc.resolve(value).as_int()).and_then(|value| u32::try_from(value).ok()) +} + // ── writing ───────────────────────────────────────────────────────────────────────────────── /// Fill the field `name`. diff --git a/crates/forms/src/tests.rs b/crates/forms/src/tests.rs index 48f767742..8a40c3665 100644 --- a/crates/forms/src/tests.rs +++ b/crates/forms/src/tests.rs @@ -95,6 +95,28 @@ fn the_field_tree_is_read_with_inheritance() { assert_eq!(field(&all, "address.city").quadding, 1); } +#[test] +fn field_flags_reject_values_outside_the_unsigned_32_bit_domain() { + let objs: Vec = vec![ + "<< /Type /Catalog /Pages 2 0 R /AcroForm 4 0 R >>".into(), + "<< /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 600 800] >>".into(), + "<< /Type /Page /Parent 2 0 R /Annots [] >>".into(), + "<< /Fields [5 0 R 6 0 R 7 0 R 8 0 R 9 0 R] >>".into(), + "<< /FT /Btn /T (valid) /Ff 65536 >>".into(), + "<< /FT /Btn /T (negative) /Ff -1 >>".into(), + "<< /FT /Btn /T (overflow) /Ff 4295032832 >>".into(), + "<< /FT /Btn /T (wrong_type) /Ff (65536) >>".into(), + "<< /FT /Btn /T (missing) >>".into(), + ]; + let all = fields(&document(&objs)); + assert_eq!(field(&all, "valid").kind, FieldKind::PushButton); + assert_eq!(field(&all, "valid").flags, flags::PUSH_BUTTON); + for name in ["negative", "overflow", "wrong_type", "missing"] { + assert_eq!(field(&all, name).kind, FieldKind::CheckBox, "{name}"); + assert_eq!(field(&all, name).flags, 0, "{name}"); + } +} + /// Some writers leave every field out of `/Fields` and put the widgets only in the page /// annotations: the tree walk alone finds nothing, and Acrobat and the browsers fill them anyway. /// The pages' widgets are adopted as fields, after the listed tree fields.