From eddae3f23a7be54e36fd6ba7a8af60e32dbda974 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Mon, 26 Oct 2026 12:27:57 -0400 Subject: [PATCH] Cap UTF-8 character collection at the remaining text allowance block_chars collected a whole Utf8 string before read checked MAX_CHARS, so an oversized string was fully allocated first. Take at most the remaining allowance plus one, as the mixed-segment arm already does, so read still detects the overflow. Generated with Codebuff Co-Authored-By: Codebuff --- crates/affinity/src/text.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/affinity/src/text.rs b/crates/affinity/src/text.rs index 14317eb791..eb52cda436 100644 --- a/crates/affinity/src/text.rs +++ b/crates/affinity/src/text.rs @@ -69,14 +69,14 @@ pub(crate) fn read(r: &mut Reader, id: ObjId, world: Affine) -> Option { /// inline object (page number, anchor) takes one `U+FFFC` before its segment's text. Stops once /// `total` plus these characters would pass the cap. fn block_chars(s: &Stream, glyphs: ObjId, total: usize, placeholders: &mut bool) -> Vec { + // One past the allowance is enough to trip the check in `read`; both arms stop there. + let room = MAX_CHARS.saturating_sub(total).saturating_add(1); match s.str(glyphs, b"Utf8") { - Some(t) => t.chars().collect(), + Some(t) => t.chars().take(room).collect(), None => { // Inline objects (page numbers, anchors) each take one index before the segment text. let mut v = Vec::new(); - // One past the allowance is enough to trip the check below; shared segments - // repeated by reference must not expand beyond it first. - let room = MAX_CHARS.saturating_sub(total).saturating_add(1); + // Shared segments repeated by reference must not expand beyond the allowance first. for seg in s.objs(glyphs, b"Mixd") { if v.len() >= room { break;