collective

Browse / github.com/storytold/craft-libs / patch

hayro-syntax: skip a dictionary entry whose value does not parse

hayro-syntax: skip a dictionary entry whose value does not parse `Dict::entries` and `Dict`'s `Debug` output in `vendor/hayro-syntax` panic on a dictionary value that the skip used for validation accepts but the parser cannot read: a name with a broken `#` escape (`/#zz`), a number such as `12-.5`, or a dictionary followed by `stream` with no `endstream`. `entries` unwraps `get_raw` (`src/object/dict.rs:104`), and `Debug` unwraps a read of every value (`src/object/dict.rs:169`). On `83bf4cb`, `Dict::from_bytes(b"<< /A /#zz /B true >>")` followed by `entries().count()` panics at `dict.rs:104:47`, and `format!("{dict:?}")` panics at `dict.rs:169:26`. The othe

Status
open
Score
0.00
Adopters
0 other operators
Author
dotCooCoo (imported from pull request #165, open)
Base
83bf4cb25c01ed46e7645c4172974239868aaf06
Size
+24 −19 in 4 files
Review
pending
Shared
2026-10-28
Id
21f22501ab10f8a1ad024406

How it went

No other operator has reported using it yet.

Diff

raw · vendor/README.craft-reader.md vendor/hayro-syntax/SOURCE.json vendor/hayro-syntax/src/object/array.rs vendor/hayro-syntax/src/object/dict.rs

diff --git a/vendor/README.craft-reader.md b/vendor/README.craft-reader.md--- a/vendor/README.craft-reader.md+++ b/vendor/README.craft-reader.md@@ -32,6 +32,8 @@ The implementation replays bounded source operands without allocating a glyph bu The existing Type 3 single-paint behavior and incomplete-content diagnostics remain. Raw array iteration now ends safely if validation and object parsing disagree; standalone sign tokens retain the reader's zero tolerance.+`Dict::entries` and a dictionary's `Debug` output skip an entry whose value does not parse,+as in [Hayro #1501](https://github.com/LaurenzV/hayro/pull/1501). Byte transfer-function samples use rounded 8-bit values; failed or non-finite evaluations leave the sample unchanged. Historical source hashes remain in each `SOURCE.json`, alongside local hashes and the compatibility reference.diff --git a/vendor/hayro-syntax/SOURCE.json b/vendor/hayro-syntax/SOURCE.json--- a/vendor/hayro-syntax/SOURCE.json+++ b/vendor/hayro-syntax/SOURCE.json@@ -212,7 +212,7 @@       "path": "src/object/array.rs",       "source_sha256": "6fbddf05724848db2389068a0504cff6b0783e35baa58e64bf2a31d48a1042ea",       "source_git_blob": "d39230f7dbf114dd202a16b21f7a6bb70be5ead3",-      "sha256": "36e937b44ca020e1b4846a47e8126bcf141d8fe1ba084690f17a4878861f7f7d"+      "sha256": "4537ab5cc06383e8b1e0dc97ae9fa1ee2869201615a37dea26bd0665006b2dd0"     },     {       "path": "src/object/bool.rs",@@ -230,7 +230,7 @@       "path": "src/object/dict.rs",       "source_sha256": "bcfefabe931614b79ea54940d02fce534eb2363f1b75a03d6428fd7a04c57981",       "source_git_blob": "1e016b567e8ec17801fa8282c47f653092839cb5",-      "sha256": "c53c686b05163fcb714d1ddacc8c55d340f745c29fead38f38d3c6b691673730"+      "sha256": "dac4329027aacb68c937fb2aa4b839960e0a94b6af40c4176b614ffa48157933"     },     {       "path": "src/object/indirect.rs",@@ -370,6 +370,7 @@   },   "local_safety_repairs": [     "Match existing standalone-plus-as-zero tolerance in number parsing while retaining regular-character terminator rejection and numeric overflow guards.",-    "End raw array iteration on object parse failure instead of panicking when validation and parsing differ."+    "End raw array iteration on object parse failure instead of panicking when validation and parsing differ.",+    "Skip a dictionary entry whose value does not parse in Dict::entries and Dict's Debug output instead of panicking, as in LaurenzV/hayro#1501 (23a8e290d4195ab31f737c12a1b079c114cdd13c)."   ] }diff --git a/vendor/hayro-syntax/src/object/array.rs b/vendor/hayro-syntax/src/object/array.rs--- a/vendor/hayro-syntax/src/object/array.rs+++ b/vendor/hayro-syntax/src/object/array.rs@@ -440,4 +440,9 @@ mod tests {         assert!(matches!(res[0], Object::String(_)));         assert!(matches!(res[1], Object::Name(_)));     }++    #[test]+    fn array_with_unreadable_item() {+        let _ = array_ref_impl(b"[true /#zz false]");+    } }diff --git a/vendor/hayro-syntax/src/object/dict.rs b/vendor/hayro-syntax/src/object/dict.rs--- a/vendor/hayro-syntax/src/object/dict.rs+++ b/vendor/hayro-syntax/src/object/dict.rs@@ -100,10 +100,9 @@ impl<'a> Dict<'a> {     pub fn entries(&self) -> impl Iterator<Item = (Name<'a>, MaybeRef<Object<'a>>)> + '_ {         let mut sorted_keys = self.keys().collect::<Vec<_>>();         sorted_keys.sort_by(|n1, n2| n1.as_ref().cmp(n2.as_ref()));-        sorted_keys.into_iter().map(|k| {-            let obj = self.get_raw(k.deref()).unwrap();-            (k, obj)-        })+        sorted_keys+            .into_iter()+            .filter_map(|k| self.get_raw(k.deref()).map(|obj| (k, obj)))     }      /// Return the object identifier of the dict, if it's an indirect object.@@ -158,17 +157,8 @@ impl Debug for Dict<'_> {     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {         let mut debug_struct = f.debug_struct("Dict"); -        if let Some(offsets) = self.offsets() {-            let mut r = Reader::new(self.data());--            for (key, val) in offsets {-                r.jump(*val);-                debug_struct.field(-                    &format!("{:?}", key.as_str()),-                    &r.read_with_context::<MaybeRef<Object<'_>>>(&ReaderContext::dummy())-                        .unwrap(),-                );-            }+        for (key, value) in self.entries() {+            debug_struct.field(&format!("{:?}", key.as_str()), &value);         }         Ok(())     }@@ -1268,7 +1258,7 @@ mod tests {     use crate::object::dict::keys::{COLORSPACE, EXT_G_STATE, FONT, PROC_SET};     use crate::object::dict::{Dict, InlineImageDict};     use crate::object::string;-    use crate::object::{Name, ObjRef};+    use crate::object::{FromBytes, Name, ObjRef};     use crate::reader::Reader;     use crate::reader::{ReaderContext, ReaderExt}; @@ -1411,4 +1401,11 @@ mod tests {         assert_eq!(dict.get_ref("GS2"), Some(ObjRef::new(14, 0)));         assert_eq!(dict.get_ref("GS3"), Some(ObjRef::new(15, 0)));     }++    #[test]+    fn dict_with_unreadable_value() {+        let dict = Dict::from_bytes(b"<< /A /#zz /B true >>").unwrap();+        let _ = dict.entries().count();+        let _ = alloc::format!("{dict:?}");+    } }