otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount; FT_UInt count1, count2; OTV_ENTER; p += 2; /* skip Format */ OTV_LIMIT_CHECK( 2 ); BacktrackGlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount )); OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 ); for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); InputGlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount )); OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 ); for ( count1 = InputGlyphCount; count1 > 0; count1-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); LookaheadGlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount )); OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 ); for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); count2 = FT_NEXT_USHORT( p ); OTV_TRACE(( " (Count = %d)\n", count2 )); OTV_LIMIT_CHECK( count2 * 4 ); for ( ; count2 > 0; count2-- ) { if ( FT_NEXT_USHORT( p ) >= InputGlyphCount ) FT_INVALID_DATA; if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count ) FT_INVALID_DATA; } OTV_EXIT; }
static void otv_MathVariants_validate( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_UInt vcnt, hcnt, i, table_size; OTV_OPTIONAL_TABLE( VCoverage ); OTV_OPTIONAL_TABLE( HCoverage ); OTV_OPTIONAL_TABLE( Offset ); OTV_NAME_ENTER( "MathVariants" ); OTV_LIMIT_CHECK( 10 ); p += 2; /* Skip the MinConnectorOverlap constant */ OTV_OPTIONAL_OFFSET( VCoverage ); OTV_OPTIONAL_OFFSET( HCoverage ); vcnt = FT_NEXT_USHORT( p ); hcnt = FT_NEXT_USHORT( p ); OTV_LIMIT_CHECK( 2 * vcnt + 2 * hcnt ); table_size = 10 + 2 * vcnt + 2 * hcnt; OTV_SIZE_CHECK( VCoverage ); if ( VCoverage ) otv_Coverage_validate( table + VCoverage, valid, vcnt ); OTV_SIZE_CHECK( HCoverage ); if ( HCoverage ) otv_Coverage_validate( table + HCoverage, valid, hcnt ); for ( i = 0; i < vcnt; ++i ) { OTV_OPTIONAL_OFFSET( Offset ); OTV_SIZE_CHECK( Offset ); otv_MathGlyphConstruction_validate( table + Offset, valid ); } for ( i = 0; i < hcnt; ++i ) { OTV_OPTIONAL_OFFSET( Offset ); OTV_SIZE_CHECK( Offset ); otv_MathGlyphConstruction_validate( table + Offset, valid ); } OTV_EXIT; }
static void otv_O_x_Ox( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_Bytes Coverage; FT_UInt GlyphCount; OTV_Validate_Func func; OTV_ENTER; OTV_LIMIT_CHECK( 4 ); Coverage = table + FT_NEXT_USHORT( p ); GlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); otv_Coverage_validate( Coverage, valid, GlyphCount ); if ( GlyphCount != otv_Coverage_get_count( Coverage ) ) FT_INVALID_DATA; OTV_LIMIT_CHECK( GlyphCount * 2 ); valid->nesting_level++; func = valid->func[valid->nesting_level]; valid->extra1 = 0; for ( ; GlyphCount > 0; GlyphCount-- ) func( table + FT_NEXT_USHORT( p ), valid ); valid->nesting_level--; OTV_EXIT; }
otv_u_x_y_Ox_sy( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt GlyphCount, Count, count1; OTV_ENTER; p += 2; /* skip Format */ OTV_LIMIT_CHECK( 4 ); GlyphCount = FT_NEXT_USHORT( p ); Count = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); OTV_TRACE(( " (Count = %d)\n", Count )); OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 ); for ( count1 = GlyphCount; count1 > 0; count1-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); for ( ; Count > 0; Count-- ) { if ( FT_NEXT_USHORT( p ) >= GlyphCount ) FT_INVALID_DATA; if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count ) FT_INVALID_DATA; } OTV_EXIT; }
otv_u_C_x_Ox( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt Count, Coverage; OTV_Validate_Func func; OTV_ENTER; p += 2; /* skip Format */ OTV_LIMIT_CHECK( 4 ); Coverage = FT_NEXT_USHORT( p ); Count = FT_NEXT_USHORT( p ); OTV_TRACE(( " (Count = %d)\n", Count )); otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)Count ); OTV_LIMIT_CHECK( Count * 2 ); otvalid->nesting_level++; func = otvalid->func[otvalid->nesting_level]; for ( ; Count > 0; Count-- ) func( table + FT_NEXT_USHORT( p ), otvalid ); otvalid->nesting_level--; OTV_EXIT; }
otv_u_O_O_O_O_x_Onx( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt Coverage; FT_UInt BacktrackClassDef, InputClassDef, LookaheadClassDef; FT_UInt ChainClassSetCount; OTV_Validate_Func func; OTV_ENTER; p += 2; /* skip Format */ OTV_LIMIT_CHECK( 10 ); Coverage = FT_NEXT_USHORT( p ); BacktrackClassDef = FT_NEXT_USHORT( p ); InputClassDef = FT_NEXT_USHORT( p ); LookaheadClassDef = FT_NEXT_USHORT( p ); ChainClassSetCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount )); otv_Coverage_validate( table + Coverage, otvalid, -1 ); otv_ClassDef_validate( table + BacktrackClassDef, otvalid ); otv_ClassDef_validate( table + InputClassDef, otvalid ); otv_ClassDef_validate( table + LookaheadClassDef, otvalid ); OTV_LIMIT_CHECK( ChainClassSetCount * 2 ); otvalid->nesting_level++; func = otvalid->func[otvalid->nesting_level]; otvalid->extra1 = otvalid->lookup_count; for ( ; ChainClassSetCount > 0; ChainClassSetCount-- ) { FT_UInt offset = FT_NEXT_USHORT( p ); if ( offset ) func( table + offset, otvalid ); } otvalid->nesting_level--; OTV_EXIT; }
static void otv_MathItalicsCorrectionInfo_validate( FT_Bytes table, OTV_Validator otvalid, FT_Int isItalic ) { FT_Bytes p = table; FT_UInt i, cnt, table_size; OTV_OPTIONAL_TABLE( Coverage ); OTV_OPTIONAL_TABLE( DeviceTableOffset ); FT_UNUSED( isItalic ); /* only used if tracing is active */ OTV_NAME_ENTER( isItalic ? "MathItalicsCorrectionInfo" : "MathTopAccentAttachment" ); OTV_LIMIT_CHECK( 4 ); OTV_OPTIONAL_OFFSET( Coverage ); cnt = FT_NEXT_USHORT( p ); OTV_LIMIT_CHECK( 4 * cnt ); table_size = 4 + 4 * cnt; OTV_SIZE_CHECK( Coverage ); otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)cnt ); for ( i = 0; i < cnt; ++i ) { p += 2; /* Skip the value */ OTV_OPTIONAL_OFFSET( DeviceTableOffset ); OTV_SIZE_CHECK( DeviceTableOffset ); if ( DeviceTableOffset ) otv_Device_validate( table + DeviceTableOffset, otvalid ); } OTV_EXIT; }
static void otv_MathGlyphInfo_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt MathItalicsCorrectionInfo, MathTopAccentAttachment; FT_UInt ExtendedShapeCoverage, MathKernInfo; OTV_NAME_ENTER( "MathGlyphInfo" ); OTV_LIMIT_CHECK( 8 ); MathItalicsCorrectionInfo = FT_NEXT_USHORT( p ); MathTopAccentAttachment = FT_NEXT_USHORT( p ); ExtendedShapeCoverage = FT_NEXT_USHORT( p ); MathKernInfo = FT_NEXT_USHORT( p ); if ( MathItalicsCorrectionInfo ) otv_MathItalicsCorrectionInfo_validate( table + MathItalicsCorrectionInfo, otvalid, TRUE ); /* Italic correction and Top Accent Attachment have the same format */ if ( MathTopAccentAttachment ) otv_MathItalicsCorrectionInfo_validate( table + MathTopAccentAttachment, otvalid, FALSE ); if ( ExtendedShapeCoverage ) { OTV_NAME_ENTER( "ExtendedShapeCoverage" ); otv_Coverage_validate( table + ExtendedShapeCoverage, otvalid, -1 ); OTV_EXIT; } if ( MathKernInfo ) otv_MathKernInfo_validate( table + MathKernInfo, otvalid ); OTV_EXIT; }
static void otv_MathKernInfo_validate( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_UInt i, j, cnt, table_size; OTV_OPTIONAL_TABLE( Coverage ); OTV_OPTIONAL_TABLE( MKRecordOffset ); OTV_NAME_ENTER( "MathKernInfo" ); OTV_LIMIT_CHECK( 4 ); OTV_OPTIONAL_OFFSET( Coverage ); cnt = FT_NEXT_USHORT( p ); OTV_LIMIT_CHECK( 8 * cnt ); table_size = 4 + 8 * cnt; OTV_SIZE_CHECK( Coverage ); otv_Coverage_validate( table + Coverage, valid, cnt ); for ( i = 0; i < cnt; ++i ) { for ( j = 0; j < 4; ++j ) { OTV_OPTIONAL_OFFSET( MKRecordOffset ); OTV_SIZE_CHECK( MKRecordOffset ); if ( MKRecordOffset ) otv_MathKern_validate( table + MKRecordOffset, valid ); } } OTV_EXIT; }
static void otv_MarkGlyphSets_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt MarkGlyphSetCount; OTV_NAME_ENTER( "MarkGlyphSets" ); p += 2; /* skip Format */ OTV_LIMIT_CHECK( 2 ); MarkGlyphSetCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (MarkGlyphSetCount = %d)\n", MarkGlyphSetCount )); OTV_LIMIT_CHECK( MarkGlyphSetCount * 4 ); /* CoverageOffsets */ for ( ; MarkGlyphSetCount > 0; MarkGlyphSetCount-- ) otv_Coverage_validate( table + FT_NEXT_ULONG( p ), otvalid, -1 ); OTV_EXIT; }
static void otv_ReverseChainSingleSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table, Coverage; FT_UInt SubstFormat; FT_UInt BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount; OTV_NAME_ENTER( "ReverseChainSingleSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: /* ReverseChainSingleSubstFormat1 */ OTV_LIMIT_CHECK( 4 ); Coverage = table + FT_NEXT_USHORT( p ); BacktrackGlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount )); otv_Coverage_validate( Coverage, otvalid, -1 ); OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 ); for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); LookaheadGlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount )); OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 ); for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- ) otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 ); GlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); if ( GlyphCount != otv_Coverage_get_count( Coverage ) ) FT_INVALID_DATA; OTV_LIMIT_CHECK( GlyphCount * 2 ); /* Substitute */ for ( ; GlyphCount > 0; GlyphCount-- ) if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count ) FT_INVALID_DATA; break; default: FT_INVALID_FORMAT; } OTV_EXIT; }
static void otv_SingleSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "SingleSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: /* SingleSubstFormat1 */ { FT_Bytes Coverage; FT_Int DeltaGlyphID; FT_Long idx; OTV_LIMIT_CHECK( 4 ); Coverage = table + FT_NEXT_USHORT( p ); DeltaGlyphID = FT_NEXT_SHORT( p ); otv_Coverage_validate( Coverage, otvalid, -1 ); idx = (FT_Long)otv_Coverage_get_first( Coverage ) + DeltaGlyphID; if ( idx < 0 ) FT_INVALID_DATA; idx = (FT_Long)otv_Coverage_get_last( Coverage ) + DeltaGlyphID; if ( (FT_UInt)idx >= otvalid->glyph_count ) FT_INVALID_DATA; } break; case 2: /* SingleSubstFormat2 */ { FT_UInt Coverage, GlyphCount; OTV_LIMIT_CHECK( 4 ); Coverage = FT_NEXT_USHORT( p ); GlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)GlyphCount ); OTV_LIMIT_CHECK( GlyphCount * 2 ); /* Substitute */ for ( ; GlyphCount > 0; GlyphCount-- ) if ( FT_NEXT_USHORT( p ) >= otvalid->glyph_count ) FT_INVALID_GLYPH_ID; } break; default: FT_INVALID_FORMAT; } OTV_EXIT; }