otv_Lookup_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt LookupType, SubTableCount; OTV_Validate_Func validate; OTV_NAME_ENTER( "Lookup" ); OTV_LIMIT_CHECK( 6 ); LookupType = FT_NEXT_USHORT( p ); p += 2; /* skip LookupFlag */ SubTableCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (type %d)\n", LookupType )); if ( LookupType == 0 || LookupType > otvalid->type_count ) FT_INVALID_DATA; validate = otvalid->type_funcs[LookupType - 1]; OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount )); OTV_LIMIT_CHECK( SubTableCount * 2 ); /* SubTable */ for ( ; SubTableCount > 0; SubTableCount-- ) validate( table + FT_NEXT_USHORT( p ), otvalid ); OTV_EXIT; }
static void otv_MathConstants_validate( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_UInt i; FT_UInt table_size; OTV_OPTIONAL_TABLE( DeviceTableOffset ); OTV_NAME_ENTER( "MathConstants" ); /* 56 constants, 51 have device tables */ OTV_LIMIT_CHECK( 2 * ( 56 + 51 ) ); table_size = 2 * ( 56 + 51 ); p += 4 * 2; /* First 4 constants have no device tables */ for ( i = 0; i < 51; ++i ) { p += 2; /* skip the value */ OTV_OPTIONAL_OFFSET( DeviceTableOffset ); OTV_SIZE_CHECK( DeviceTableOffset ); if ( DeviceTableOffset ) otv_Device_validate( table + DeviceTableOffset, valid ); } OTV_EXIT; }
static void otv_MultipleSubst_validate( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "MultipleSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: valid->extra1 = valid->glyph_count; OTV_NEST2( MultipleSubstFormat1, Sequence ); OTV_RUN( table, valid ); break; default: FT_INVALID_DATA; } OTV_EXIT; }
static void otv_Axis_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt table_size; OTV_OPTIONAL_TABLE( BaseTagList ); OTV_NAME_ENTER( "Axis" ); OTV_LIMIT_CHECK( 4 ); OTV_OPTIONAL_OFFSET( BaseTagList ); table_size = 4; OTV_SIZE_CHECK( BaseTagList ); if ( BaseTagList ) otv_BaseTagList_validate( table + BaseTagList, otvalid ); /* BaseScriptList */ otv_BaseScriptList_validate( table + FT_NEXT_USHORT( p ), otvalid ); OTV_EXIT; }
otv_Device_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt StartSize, EndSize, DeltaFormat, count; OTV_NAME_ENTER( "Device" ); OTV_LIMIT_CHECK( 8 ); StartSize = FT_NEXT_USHORT( p ); EndSize = FT_NEXT_USHORT( p ); DeltaFormat = FT_NEXT_USHORT( p ); if ( DeltaFormat < 1 || DeltaFormat > 3 ) FT_INVALID_FORMAT; if ( EndSize < StartSize ) FT_INVALID_DATA; count = EndSize - StartSize + 1; OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */ OTV_EXIT; }
otv_FeatureList_validate( FT_Bytes table, FT_Bytes lookups, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt FeatureCount; OTV_NAME_ENTER( "FeatureList" ); OTV_LIMIT_CHECK( 2 ); FeatureCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount )); OTV_LIMIT_CHECK( FeatureCount * 2 ); otvalid->lookup_count = otv_LookupList_get_count( lookups ); /* FeatureRecord */ for ( ; FeatureCount > 0; FeatureCount-- ) { p += 4; /* skip FeatureTag */ /* Feature */ otv_Feature_validate( table + FT_NEXT_USHORT( p ), otvalid ); } OTV_EXIT; }
static void otv_LigatureSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "LigatureSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature ); OTV_RUN( table, otvalid ); break; default: FT_INVALID_FORMAT; } OTV_EXIT; }
static void otv_BaseScriptList_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt BaseScriptCount; OTV_NAME_ENTER( "BaseScriptList" ); OTV_LIMIT_CHECK( 2 ); BaseScriptCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BaseScriptCount = %d)\n", BaseScriptCount )); OTV_LIMIT_CHECK( BaseScriptCount * 6 ); /* BaseScriptRecord */ for ( ; BaseScriptCount > 0; BaseScriptCount-- ) { p += 4; /* skip BaseScriptTag */ /* BaseScript */ otv_BaseScript_validate( table + FT_NEXT_USHORT( p ), otvalid ); } OTV_EXIT; }
static void otv_BaseValues_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt BaseCoordCount; OTV_NAME_ENTER( "BaseValues" ); OTV_LIMIT_CHECK( 4 ); p += 2; /* skip DefaultIndex */ BaseCoordCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BaseCoordCount = %d)\n", BaseCoordCount )); OTV_LIMIT_CHECK( BaseCoordCount * 2 ); /* BaseCoord */ for ( ; BaseCoordCount > 0; BaseCoordCount-- ) otv_BaseCoord_validate( table + FT_NEXT_USHORT( p ), otvalid ); OTV_EXIT; }
static void otv_AlternateSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "AlternateSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: otvalid->extra1 = otvalid->glyph_count; OTV_NEST2( AlternateSubstFormat1, AlternateSet ); OTV_RUN( table, otvalid ); break; default: FT_INVALID_FORMAT; } OTV_EXIT; }
otv_ScriptList_validate( FT_Bytes table, FT_Bytes features, OTV_Validator otvalid ) { FT_UInt ScriptCount; FT_Bytes p = table; OTV_NAME_ENTER( "ScriptList" ); OTV_LIMIT_CHECK( 2 ); ScriptCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount )); OTV_LIMIT_CHECK( ScriptCount * 6 ); otvalid->extra1 = otv_Feature_get_count( features ); /* ScriptRecord */ for ( ; ScriptCount > 0; ScriptCount-- ) { p += 4; /* skip ScriptTag */ otv_Script_validate( table + FT_NEXT_USHORT( p ), otvalid ); /* Script */ } OTV_EXIT; }
otv_Script_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_UInt DefaultLangSys, LangSysCount; FT_Bytes p = table; OTV_NAME_ENTER( "Script" ); OTV_LIMIT_CHECK( 4 ); DefaultLangSys = FT_NEXT_USHORT( p ); LangSysCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount )); if ( DefaultLangSys != 0 ) otv_LangSys_validate( table + DefaultLangSys, otvalid ); OTV_LIMIT_CHECK( LangSysCount * 6 ); /* LangSysRecord */ for ( ; LangSysCount > 0; LangSysCount-- ) { p += 4; /* skip LangSysTag */ /* LangSys */ otv_LangSys_validate( table + FT_NEXT_USHORT( p ), otvalid ); } OTV_EXIT; }
otv_LangSys_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt ReqFeatureIndex; FT_UInt FeatureCount; OTV_NAME_ENTER( "LangSys" ); OTV_LIMIT_CHECK( 6 ); p += 2; /* skip LookupOrder (unused) */ ReqFeatureIndex = FT_NEXT_USHORT( p ); FeatureCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex )); OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount )); if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= otvalid->extra1 ) FT_INVALID_DATA; OTV_LIMIT_CHECK( FeatureCount * 2 ); /* FeatureIndex */ for ( ; FeatureCount > 0; FeatureCount-- ) if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 ) FT_INVALID_DATA; OTV_EXIT; }
static void otv_MinMax_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt table_size; FT_UInt FeatMinMaxCount; OTV_OPTIONAL_TABLE( MinCoord ); OTV_OPTIONAL_TABLE( MaxCoord ); OTV_NAME_ENTER( "MinMax" ); OTV_LIMIT_CHECK( 6 ); OTV_OPTIONAL_OFFSET( MinCoord ); OTV_OPTIONAL_OFFSET( MaxCoord ); FeatMinMaxCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (FeatMinMaxCount = %d)\n", FeatMinMaxCount )); table_size = FeatMinMaxCount * 8 + 6; OTV_SIZE_CHECK( MinCoord ); if ( MinCoord ) otv_BaseCoord_validate( table + MinCoord, otvalid ); OTV_SIZE_CHECK( MaxCoord ); if ( MaxCoord ) otv_BaseCoord_validate( table + MaxCoord, otvalid ); OTV_LIMIT_CHECK( FeatMinMaxCount * 8 ); /* FeatMinMaxRecord */ for ( ; FeatMinMaxCount > 0; FeatMinMaxCount-- ) { p += 4; /* skip FeatureTableTag */ OTV_OPTIONAL_OFFSET( MinCoord ); OTV_OPTIONAL_OFFSET( MaxCoord ); OTV_SIZE_CHECK( MinCoord ); if ( MinCoord ) otv_BaseCoord_validate( table + MinCoord, otvalid ); OTV_SIZE_CHECK( MaxCoord ); if ( MaxCoord ) otv_BaseCoord_validate( table + MaxCoord, 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_JstfScript_validate( FT_Bytes table, OTV_Validator valid ) { FT_Bytes p = table; FT_UInt table_size; FT_UInt JstfLangSysCount; OTV_OPTIONAL_TABLE( ExtGlyph ); OTV_OPTIONAL_TABLE( DefJstfLangSys ); OTV_NAME_ENTER( "JstfScript" ); OTV_LIMIT_CHECK( 6 ); OTV_OPTIONAL_OFFSET( ExtGlyph ); OTV_OPTIONAL_OFFSET( DefJstfLangSys ); JstfLangSysCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (JstfLangSysCount = %d)\n", JstfLangSysCount )); table_size = JstfLangSysCount * 6 + 6; OTV_SIZE_CHECK( ExtGlyph ); if ( ExtGlyph ) { valid->extra1 = valid->glyph_count; OTV_NEST1( ExtenderGlyph ); OTV_RUN( table + ExtGlyph, valid ); } OTV_SIZE_CHECK( DefJstfLangSys ); if ( DefJstfLangSys ) { OTV_NEST2( JstfLangSys, JstfPriority ); OTV_RUN( table + DefJstfLangSys, valid ); } OTV_LIMIT_CHECK( 6 * JstfLangSysCount ); /* JstfLangSysRecord */ OTV_NEST2( JstfLangSys, JstfPriority ); for ( ; JstfLangSysCount > 0; JstfLangSysCount-- ) { p += 4; /* skip JstfLangSysTag */ OTV_RUN( table + FT_NEXT_USHORT( p ), valid ); } 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_ChainContextSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "ChainContextSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: /* no need to check glyph indices/classes used as input for these */ /* context rules since even invalid glyph indices/classes return */ /* meaningful results */ otvalid->extra1 = otvalid->lookup_count; OTV_NEST3( ChainContextSubstFormat1, ChainSubRuleSet, ChainSubRule ); OTV_RUN( table, otvalid ); break; case 2: /* no need to check glyph indices/classes used as input for these */ /* context rules since even invalid glyph indices/classes return */ /* meaningful results */ OTV_NEST3( ChainContextSubstFormat2, ChainSubClassSet, ChainSubClassRule ); OTV_RUN( table, otvalid ); break; case 3: OTV_NEST1( ChainContextSubstFormat3 ); OTV_RUN( table, otvalid ); break; default: FT_INVALID_FORMAT; } OTV_EXIT; }
static void otv_ExtensionSubst_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt SubstFormat; OTV_NAME_ENTER( "ExtensionSubst" ); OTV_LIMIT_CHECK( 2 ); SubstFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", SubstFormat )); switch ( SubstFormat ) { case 1: /* ExtensionSubstFormat1 */ { FT_UInt ExtensionLookupType; FT_ULong ExtensionOffset; OTV_Validate_Func validate; OTV_LIMIT_CHECK( 6 ); ExtensionLookupType = FT_NEXT_USHORT( p ); ExtensionOffset = FT_NEXT_ULONG( p ); if ( ExtensionLookupType == 0 || ExtensionLookupType == 7 || ExtensionLookupType > 8 ) FT_INVALID_DATA; validate = otvalid->type_funcs[ExtensionLookupType - 1]; validate( table + ExtensionOffset, otvalid ); } break; default: FT_INVALID_FORMAT; } OTV_EXIT; }
static void otv_BaseScript_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt table_size; FT_UInt BaseLangSysCount; OTV_OPTIONAL_TABLE( BaseValues ); OTV_OPTIONAL_TABLE( DefaultMinMax ); OTV_NAME_ENTER( "BaseScript" ); OTV_LIMIT_CHECK( 6 ); OTV_OPTIONAL_OFFSET( BaseValues ); OTV_OPTIONAL_OFFSET( DefaultMinMax ); BaseLangSysCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BaseLangSysCount = %d)\n", BaseLangSysCount )); table_size = BaseLangSysCount * 6 + 6; OTV_SIZE_CHECK( BaseValues ); if ( BaseValues ) otv_BaseValues_validate( table + BaseValues, otvalid ); OTV_SIZE_CHECK( DefaultMinMax ); if ( DefaultMinMax ) otv_MinMax_validate( table + DefaultMinMax, otvalid ); OTV_LIMIT_CHECK( BaseLangSysCount * 6 ); /* BaseLangSysRecord */ for ( ; BaseLangSysCount > 0; BaseLangSysCount-- ) { p += 4; /* skip BaseLangSysTag */ otv_MinMax_validate( table + FT_NEXT_USHORT( p ), otvalid ); } OTV_EXIT; }
static void otv_BaseTagList_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt BaseTagCount; OTV_NAME_ENTER( "BaseTagList" ); OTV_LIMIT_CHECK( 2 ); BaseTagCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (BaseTagCount = %d)\n", BaseTagCount )); OTV_LIMIT_CHECK( BaseTagCount * 4 ); /* BaselineTag */ 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_BaseCoord_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt BaseCoordFormat; OTV_NAME_ENTER( "BaseCoord" ); OTV_LIMIT_CHECK( 4 ); BaseCoordFormat = FT_NEXT_USHORT( p ); p += 2; /* skip Coordinate */ OTV_TRACE(( " (format %d)\n", BaseCoordFormat )); switch ( BaseCoordFormat ) { case 1: /* BaseCoordFormat1 */ break; case 2: /* BaseCoordFormat2 */ OTV_LIMIT_CHECK( 4 ); /* ReferenceGlyph, BaseCoordPoint */ break; case 3: /* BaseCoordFormat3 */ OTV_LIMIT_CHECK( 2 ); /* DeviceTable */ otv_Device_validate( table + FT_NEXT_USHORT( p ), otvalid ); break; default: FT_INVALID_FORMAT; } 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; }
otv_LookupList_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt LookupCount; OTV_NAME_ENTER( "LookupList" ); OTV_LIMIT_CHECK( 2 ); LookupCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (LookupCount = %d)\n", LookupCount )); OTV_LIMIT_CHECK( LookupCount * 2 ); otvalid->lookup_count = LookupCount; /* Lookup */ for ( ; LookupCount > 0; LookupCount-- ) otv_Lookup_validate( table + FT_NEXT_USHORT( p ), otvalid ); 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; }
otv_Feature_validate( FT_Bytes table, OTV_Validator otvalid ) { FT_Bytes p = table; FT_UInt LookupCount; OTV_NAME_ENTER( "Feature" ); OTV_LIMIT_CHECK( 4 ); p += 2; /* skip FeatureParams (unused) */ LookupCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (LookupCount = %d)\n", LookupCount )); OTV_LIMIT_CHECK( LookupCount * 2 ); /* LookupListIndex */ for ( ; LookupCount > 0; LookupCount-- ) if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count ) FT_INVALID_DATA; OTV_EXIT; }
otv_Coverage_validate( FT_Bytes table, OTV_Validator otvalid, FT_Int expected_count ) { FT_Bytes p = table; FT_UInt CoverageFormat; FT_UInt total = 0; OTV_NAME_ENTER( "Coverage" ); OTV_LIMIT_CHECK( 4 ); CoverageFormat = FT_NEXT_USHORT( p ); OTV_TRACE(( " (format %d)\n", CoverageFormat )); switch ( CoverageFormat ) { case 1: /* CoverageFormat1 */ { FT_UInt GlyphCount; FT_UInt i; GlyphCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); OTV_LIMIT_CHECK( GlyphCount * 2 ); /* GlyphArray */ for ( i = 0; i < GlyphCount; ++i ) { FT_UInt gid; gid = FT_NEXT_USHORT( p ); if ( gid >= otvalid->glyph_count ) FT_INVALID_GLYPH_ID; } total = GlyphCount; } break; case 2: /* CoverageFormat2 */ { FT_UInt n, RangeCount; FT_UInt Start, End, StartCoverageIndex, last = 0; RangeCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (RangeCount = %d)\n", RangeCount )); OTV_LIMIT_CHECK( RangeCount * 6 ); /* RangeRecord */ for ( n = 0; n < RangeCount; n++ ) { Start = FT_NEXT_USHORT( p ); End = FT_NEXT_USHORT( p ); StartCoverageIndex = FT_NEXT_USHORT( p ); if ( Start > End || StartCoverageIndex != total ) FT_INVALID_DATA; if ( End >= otvalid->glyph_count ) FT_INVALID_GLYPH_ID; if ( n > 0 && Start <= last ) FT_INVALID_DATA; total += End - Start + 1; last = End; } } break; default: FT_INVALID_FORMAT; } /* Generally, a coverage table offset has an associated count field. */ /* The number of glyphs in the table should match this field. If */ /* there is no associated count, a value of -1 tells us not to check. */ if ( expected_count != -1 && (FT_UInt)expected_count != total ) FT_INVALID_DATA; 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; }
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; }