Fix panic in subset when glyph_ids maps to only .notdef#133
Conversation
wezm
left a comment
There was a problem hiding this comment.
Good find, but I'm not sure the fix is the right approach though. In a scenario where only glyphs that do not have a cmap entry are retained, MappingsToKeep legitimately ends up empty. With the proposed changes an error would be returned. Instead I think that it should still build a cmap table. I.e. a cmap that is present, but has fields populated such that no glyphs are mapped.
|
Thanks for the review! You're right — returning an error is the wrong approach since empty mappings is a legitimate case. I've updated the PR to build a valid cmap table with no glyph mappings instead:
All 336 lib tests + 13 doc tests pass, |
wezm
left a comment
There was a problem hiding this comment.
Looks good overall. Just a little more iteration needed on both of the tests.
Also please squash all commits into a single commit when you're done.
| let _ = ReadScope::new(&font_data) | ||
| .read::<OpenTypeFont<'_>>() | ||
| .expect("subset output should be a valid OpenType font"); |
There was a problem hiding this comment.
This will not parse much of the font. Instead the cmap table should be parsed like test_subset_with_macroman_cmap and test_subset_with_os2_and_unicode_cmap.
| } | ||
|
|
||
| #[test] | ||
| fn subset_notdef_only_cff_produces_valid_font() { |
There was a problem hiding this comment.
We're already in a subset module, so the subset_ prefix can be removed from the test names.
When subset() is called with CmapTarget::Unicode and glyph IDs that have no cmap mapping (e.g., only glyph ID 0 / .notdef), MappingsToKeep ends up empty, causing CmapSubtableFormat4::from_mappings to panic on an unconditional unwrap(). Build a valid empty cmap table instead: - CmapSubtableFormat4::from_mappings: when mappings are empty, produce a table with only the required 0xFFFF sentinel segment - CmapSubtableFormat12::from_mappings: when mappings are empty, produce a table with an empty groups list - Add is_empty() method to MappingsToKeep<T> - Add tests for .notdef-only input with both CFF and TTF fonts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3a4dba5 to
ba1ad98
Compare
|
Thanks for the feedback! I've updated the tests to properly parse the cmap table (matching the pattern in |
|
Applied in 5fb3fff |
Summary
subset()is called withCmapTarget::Unicodeand glyph IDs that have no cmap mapping (e.g., only glyph ID 0 / .notdef),MappingsToKeepends up empty. This causesCmapSubtableFormat4::from_mappingsto panic on an unconditionalunwrap()of the first mapping iterator element.Changes
SubsetError::NoGlyphsearly insubset()when mappings are empty and the cmap target isUnicodeunwrap()inCmapSubtableFormat4::from_mappingswithErr(ParseError::BadValue)as defense-in-depthis_empty()method toMappingsToKeep<T>NoGlyphsvariant toSubsetError.notdef-only input returnsNoGlyphsinstead of panickingTest plan
cargo test --lib— 336 passed, 0 failedcargo test(all integration + doc tests) — all passedcargo fmt -- --check— cleanContext
Discovered while building a WASM-based CJK font subsetter for GJS Kanji Database. When a codemap requests a font chunk for a Unicode range that the font doesn't cover, the subsetter receives only
.notdefglyph IDs and crashes.