fix(forms): reject out-of-domain field flags (#701)

This commit is contained in:
cyfung1031
2026-10-10 06:03:49 -04:00
committed by GitHub
parent 18e5db5e6d
commit 0695fd6f16
2 changed files with 28 additions and 2 deletions
+6 -2
View File
@@ -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<u32> {
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`.
+22
View File
@@ -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<String> = 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.