[buffer] Set content_type only for the format actually being parsed (#6092)
hb_buffer_deserialize_unicode() and hb_buffer_deserialize_glyphs() each
mutated the buffer's content_type unconditionally before checking
whether the caller-supplied format was recognized, then returned false
without rolling that back for an invalid format. A buffer left with
content_type set but len == 0 fails the assert_glyphs() /
assert_unicode() invariant on a later, independent call that expects
a clean buffer, aborting the process:
- deserialize_unicode(INVALID) -> deserialize_glyphs() aborts in
assert_glyphs().
- deserialize_glyphs(INVALID) -> add_codepoints() aborts in
assert_unicode().
Move each hb_buffer_set_content_type() call into the TEXT/JSON case
bodies of the existing format switch, instead of guarding it with a
separate validity check ahead of the switch. The switch's own case
list is already the single source of truth for which formats are
supported, so this avoids duplicating that knowledge in a second
condition that could drift out of sync with the switch.
Testing:
- Built with -Db_sanitize=address,undefined.
- Reproduced both original aborts against the unfixed code
(SIGABRT via assert_glyphs()/assert_unicode()).
- Rebuilt with the fix and reran both reproducers: clean exit, no
assertion failure.
- Ran the full test suite (meson test, sanitizer build, FreeType +
ICU enabled) before and after: 71/75 pass in both, with the same
4 pre-existing failures unrelated to buffer serialization
(check-libstdc++, and the experimental vector/raster/gpu-fuzzer
chunk 2 targets) - confirmed to fail identically on the
unmodified baseline, so no regressions from this change.
Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc
index 923524d..3aa48b6 100644
--- a/src/hb-buffer-serialize.cc
+++ b/src/hb-buffer-serialize.cc
@@ -796,19 +796,19 @@
return false;
}
- hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
-
if (!font)
font = hb_font_get_empty ();
switch (format)
{
case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
+ hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
return _hb_buffer_deserialize_text_glyphs (buffer,
buf, buf_len, end_ptr,
font);
case HB_BUFFER_SERIALIZE_FORMAT_JSON:
+ hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
return _hb_buffer_deserialize_json (buffer,
buf, buf_len, end_ptr,
font);
@@ -867,18 +867,18 @@
return false;
}
- hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
-
hb_font_t* font = hb_font_get_empty ();
switch (format)
{
case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
+ hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
return _hb_buffer_deserialize_text_unicode (buffer,
buf, buf_len, end_ptr,
font);
case HB_BUFFER_SERIALIZE_FORMAT_JSON:
+ hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_UNICODE);
return _hb_buffer_deserialize_json (buffer,
buf, buf_len, end_ptr,
font);