static void gxv_mort_subtable_type2_ligActionOffset_validate( FT_Bytes table, FT_UShort ligActionOffset, GXV_Validator valid ) { /* access ligActionTable */ GXV_mort_subtable_type2_StateOptRecData optdata = (GXV_mort_subtable_type2_StateOptRecData)valid->statetable.optdata; FT_Bytes lat_base = table + optdata->ligActionTable; FT_Bytes p = table + ligActionOffset; FT_Bytes lat_limit = lat_base + optdata->ligActionTable; GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset ); if ( p < lat_base ) { GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n", ligActionOffset, lat_base - p )); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; } else if ( lat_limit < p ) { GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n", ligActionOffset, p - lat_limit )); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ if ( valid->root->level >= FT_VALIDATE_PARANOID ) FT_INVALID_OFFSET; } else { /* validate entry in ligActionTable */ FT_ULong lig_action; FT_UShort last; FT_UShort store; FT_ULong offset; lig_action = FT_NEXT_ULONG( p ); last = (FT_UShort)( ( lig_action >> 31 ) & 1 ); store = (FT_UShort)( ( lig_action >> 30 ) & 1 ); offset = lig_action & 0x3FFFFFFFUL; } }
gxv_mort_validate( FT_Bytes table, FT_Face face, FT_Validator ftvalid ) { GXV_ValidatorRec validrec; GXV_Validator valid = &validrec; FT_Bytes p = table; FT_Bytes limit = 0; FT_ULong version; FT_ULong nChains; FT_ULong i; valid->root = ftvalid; valid->face = face; limit = valid->root->limit; FT_TRACE3(( "validating `mort' table\n" )); GXV_INIT; GXV_LIMIT_CHECK( 4 + 4 ); version = FT_NEXT_ULONG( p ); nChains = FT_NEXT_ULONG( p ); if (version != 0x00010000UL) FT_INVALID_FORMAT; for ( i = 0; i < nChains; i++ ) { GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains )); GXV_32BIT_ALIGNMENT_VALIDATE( p - table ); gxv_mort_chain_validate( p, limit, valid ); p += valid->subtable_length; } FT_TRACE4(( "\n" )); }
gxv_trak_validate( FT_Bytes table, FT_Face face, FT_Validator ftvalid ) { FT_Bytes p = table; FT_Bytes limit = 0; GXV_ValidatorRec gxvalidrec; GXV_Validator gxvalid = &gxvalidrec; GXV_trak_DataRec trakrec; GXV_trak_Data trak = &trakrec; FT_ULong version; FT_UShort format; FT_UShort horizOffset; FT_UShort vertOffset; FT_UShort reserved; GXV_ODTECT( 3, odtect ); GXV_ODTECT_INIT( odtect ); gxvalid->root = ftvalid; gxvalid->table_data = trak; gxvalid->face = face; limit = gxvalid->root->limit; FT_TRACE3(( "validating `trak' table\n" )); GXV_INIT; GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 + 2 ); version = FT_NEXT_ULONG( p ); format = FT_NEXT_USHORT( p ); horizOffset = FT_NEXT_USHORT( p ); vertOffset = FT_NEXT_USHORT( p ); reserved = FT_NEXT_USHORT( p ); GXV_TRACE(( " (version = 0x%08x)\n", version )); GXV_TRACE(( " (format = 0x%04x)\n", format )); GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset )); GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset )); GXV_TRACE(( " (reserved = 0x%04x)\n", reserved )); /* Version 1.0 (always:1996) */ if ( version != 0x00010000UL ) FT_INVALID_FORMAT; /* format 0 (always:1996) */ if ( format != 0x0000 ) FT_INVALID_FORMAT; GXV_32BIT_ALIGNMENT_VALIDATE( horizOffset ); GXV_32BIT_ALIGNMENT_VALIDATE( vertOffset ); /* Reserved Fixed Value (always) */ if ( reserved != 0x0000 ) FT_INVALID_DATA; /* validate trackData */ if ( 0 < horizOffset ) { gxv_trak_trackData_validate( table + horizOffset, limit, gxvalid ); gxv_odtect_add_range( table + horizOffset, gxvalid->subtable_length, "horizJustData", odtect ); } if ( 0 < vertOffset ) { gxv_trak_trackData_validate( table + vertOffset, limit, gxvalid ); gxv_odtect_add_range( table + vertOffset, gxvalid->subtable_length, "vertJustData", odtect ); } gxv_odtect_validate( odtect, gxvalid ); FT_TRACE4(( "\n" )); }
static void gxv_mort_subtable_type2_ligActionOffset_validate( FT_Bytes table, FT_UShort ligActionOffset, GXV_Validator gxvalid) { /* access ligActionTable */ GXV_mort_subtable_type2_StateOptRecData optdata = (GXV_mort_subtable_type2_StateOptRecData)gxvalid->statetable.optdata; FT_Bytes lat_base = table + optdata->ligActionTable; FT_Bytes p = table + ligActionOffset; FT_Bytes lat_limit = lat_base + optdata->ligActionTable; GXV_32BIT_ALIGNMENT_VALIDATE(ligActionOffset); if (p < lat_base) { GXV_TRACE(("too short offset 0x%04x: p < lat_base (%d byte rewind)\n", ligActionOffset, lat_base - p)); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET); } else if (lat_limit < p) { GXV_TRACE(("too large offset 0x%04x: lat_limit < p (%d byte overrun)\n", ligActionOffset, p - lat_limit)); /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */ GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET); } else { /* validate entry in ligActionTable */ FT_ULong lig_action; #ifdef GXV_LOAD_UNUSED_VARS FT_UShort last; FT_UShort store; #endif FT_ULong offset; lig_action = FT_NEXT_ULONG(p); #ifdef GXV_LOAD_UNUSED_VARS last = (FT_UShort)((lig_action >> 31) & 1); store = (FT_UShort)((lig_action >> 30) & 1); #endif /* Apple spec defines this offset as a word offset */ offset = lig_action & 0x3FFFFFFFUL; if (offset * 2 < optdata->ligatureTable) { GXV_TRACE(("too short offset 0x%08x:" " 2 x offset < ligatureTable (%d byte rewind)\n", offset, optdata->ligatureTable - offset * 2)); GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET); } else if (offset * 2 > optdata->ligatureTable + optdata->ligatureTable_length) { GXV_TRACE(("too long offset 0x%08x:" " 2 x offset > ligatureTable + ligatureTable_length" " (%d byte overrun)\n", offset, optdata->ligatureTable + optdata->ligatureTable_length - offset * 2)); GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET); } } }