From daf224755a83e425d7eedd68e53df056dd3b0ed0 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 4 Nov 2026 03:45:10 +0000 Subject: [PATCH] Fonts: cap the name records and decoded bytes read per name id --- crates/text/src/fontdb/names.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/text/src/fontdb/names.rs b/crates/text/src/fontdb/names.rs index fe0e24cc0..b4eb8711b 100644 --- a/crates/text/src/fontdb/names.rs +++ b/crates/text/src/fontdb/names.rs @@ -76,9 +76,23 @@ pub(super) fn name(font: &skrifa::FontRef<'_>, ids: &[StringId]) -> Option, id: StringId) -> Vec<(Option, String)> { - font.localized_strings(id).map(|s| (s.language().map(str::to_owned), s.to_string())).filter(|(_, s)| !s.is_empty()).collect() + let mut bytes = 0usize; + font.localized_strings(id) + .take(MAX_NAME_RECORDS) + .map(|s| (s.language().map(str::to_owned), s.to_string())) + .take_while(|(_, s)| { + bytes = bytes.saturating_add(s.len()); + bytes <= MAX_NAME_BYTES + }) + .filter(|(_, s)| !s.is_empty()) + .collect() } /// Whether a name-table language tag is English (Illustrator's "Show Font Names in English"). @@ -119,3 +133,17 @@ pub(super) fn norm_chars(s: &str) -> impl Iterator + '_ { pub(super) fn norm(s: &str) -> String { norm_chars(s).collect() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn a_name_table_of_many_records_is_cut_short() { + let many: Vec<(u16, &str)> = (0..2000).map(|_| (1, "Short")).collect(); + let name = crate::test_fonts::name_table(&many).unwrap_or_default(); + let font = crate::fontdb::sfnt_of(&[(b"name", &name)]).unwrap_or_default(); + let font = skrifa::FontRef::new(&font).unwrap(); + assert_eq!(localized(&font, StringId::FAMILY_NAME).len(), MAX_NAME_RECORDS); + } +}