[autofit] Fix handling of invalid GSUB lookup indices.

Problem reported by Marc Schönefeld.

HarfBuzz validates everything while processing OpenType tables in fonts.
However, the data returned by `hb_ot_layout_collect_lookups` is not
validated.  This commit adds proper checks.

* src/autofit/afglobal.h (AF_FaceGlobals): New field `gsub_lookup_count`.
* src/autofit/afgsub.c (af_parse_gsub): Set it.

* src/autofit/afadjust.c (af_reverse_character_map_new): Test result of
  `hb_set_next`.
This commit is contained in:
Werner Lemberg
2025-11-27 08:24:26 +01:00
parent b848824d10
commit 582cea9ee1
3 changed files with 15 additions and 3 deletions

View File

@@ -1405,7 +1405,8 @@
FT_TRACE4(( " " ));
idx = HB_SET_VALUE_INVALID;
while ( hb( set_next )( gsub_lookups, &idx ) )
if ( globals->gsub_lookups_single_alternate[idx] )
if ( idx < globals->gsub_lookup_count &&
globals->gsub_lookups_single_alternate[idx] )
{
have_idx = TRUE;
FT_TRACE4(( " %u", idx ));
@@ -1428,9 +1429,17 @@
idx = HB_SET_VALUE_INVALID;
while ( hb( set_next )( gsub_lookups, &idx ) )
{
FT_UInt32 offset = globals->gsub_lookups_single_alternate[idx];
FT_UInt32 offset;
/* HarfBuzz only validates lookup indices while */
/* processing lookups, not while collecting them, */
/* so we have to do that by ourselves. */
if ( idx < globals->gsub_lookup_count )
offset = globals->gsub_lookups_single_alternate[idx];
else
offset = 0;
/* Put all substitutions into a single hash table. Note that */
/* the hash values usually contain more than a single character */
/* code; this can happen if different 'SingleSubst' subtables */

View File

@@ -116,7 +116,9 @@ FT_BEGIN_HEADER
/* The GSUB table. */
FT_Byte* gsub;
/* Lookup offsets, with only SingleSubst and AlternateSubst non-NULL. */
/* An array of lookup offsets (of `gsub_lookup_count` elements), */
/* with only SingleSubst and AlternateSubst lookups non-NULL. */
FT_UShort gsub_lookup_count;
FT_UInt32* gsub_lookups_single_alternate;
#endif

View File

@@ -364,6 +364,7 @@
}
globals->gsub = gsub;
globals->gsub_lookup_count = lookupCount;
globals->gsub_lookups_single_alternate = gsub_lookups_single_alternate;
return;