ref: 3f1905b191b692e94c3e600ab68f5213aea7caa9
parent: d76fe5a1af5fb9a08b38d4d426688ee9cd34996b
author: Werner Lemberg <[email protected]>
date: Sat Aug 11 11:45:32 EDT 2007
* src/otvalid/otvcommn.c, src/otvalid/otvcommn.h (otv_Coverage_validate): Add fourth argument to pass an expected count value. Update all users. Check glyph IDs. (otv_ClassDef_validate): Check `StartGlyph'. * src/otvalid/otvgsub.c (otv_SingleSubst_validate): More glyph ID checks. * src/otvalid/otvmath.c (otv_MathConstants_validate): There are only 56 constants. (otv_GlyphAssembly_validate, otv_MathGlyphConstruction_validate): Check glyph IDs.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-08-11 George Williams <[email protected]>
+
+ * src/otvalid/otvcommn.c, src/otvalid/otvcommn.h
+ (otv_Coverage_validate): Add fourth argument to pass an expected
+ count value. Update all users.
+ Check glyph IDs.
+ (otv_ClassDef_validate): Check `StartGlyph'.
+
+ * src/otvalid/otvgsub.c (otv_SingleSubst_validate): More glyph ID
+ checks.
+
+ * src/otvalid/otvmath.c (otv_MathConstants_validate): There are only
+ 56 constants.
+ (otv_GlyphAssembly_validate, otv_MathGlyphConstruction_validate):
+ Check glyph IDs.
+
2007-08-08 Werner Lemberg <[email protected]>
* src/otvalid/otvbase.c, src/otvalid/otvcommn.c,
--- a/src/otvalid/otvcommn.c
+++ b/src/otvalid/otvcommn.c
@@ -39,10 +39,12 @@
FT_LOCAL_DEF( void )
otv_Coverage_validate( FT_Bytes table,
- OTV_Validator valid )
+ OTV_Validator valid,
+ FT_Int expected_count )
{
FT_Bytes p = table;
FT_UInt CoverageFormat;
+ FT_UInt total = 0;
OTV_NAME_ENTER( "Coverage" );
@@ -57,6 +59,7 @@
case 1: /* CoverageFormat1 */
{
FT_UInt GlyphCount;
+ FT_UInt i;
GlyphCount = FT_NEXT_USHORT( p );
@@ -64,6 +67,18 @@
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 >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
+ }
+
+ total = GlyphCount;
}
break;
@@ -70,7 +85,7 @@
case 2: /* CoverageFormat2 */
{
FT_UInt n, RangeCount;
- FT_UInt Start, End, StartCoverageIndex, total = 0, last = 0;
+ FT_UInt Start, End, StartCoverageIndex, last = 0;
RangeCount = FT_NEXT_USHORT( p );
@@ -89,6 +104,9 @@
if ( Start > End || StartCoverageIndex != total )
FT_INVALID_DATA;
+ if ( End >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
+
if ( n > 0 && Start <= last )
FT_INVALID_DATA;
@@ -102,8 +120,11 @@
FT_INVALID_FORMAT;
}
- /* no need to check glyph indices used as input to coverage tables */
- /* since even invalid glyph indices return a meaningful result */
+ /* 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;
}
@@ -215,18 +236,21 @@
{
case 1: /* ClassDefFormat1 */
{
+ FT_UInt StartGlyph;
FT_UInt GlyphCount;
- p += 2; /* skip StartGlyph */
+ OTV_LIMIT_CHECK( 4 );
- OTV_LIMIT_CHECK( 2 );
-
+ StartGlyph = FT_NEXT_USHORT( p );
GlyphCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
OTV_LIMIT_CHECK( GlyphCount * 2 ); /* ClassValueArray */
+
+ if ( StartGlyph + GlyphCount - 1 >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
}
break;
@@ -252,6 +276,9 @@
if ( Start > End || ( n > 0 && Start <= last ) )
FT_INVALID_DATA;
+ if ( End >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
+
last = End;
}
}
@@ -660,7 +687,7 @@
OTV_TRACE(( " (Count = %d)\n", Count ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, Count );
OTV_LIMIT_CHECK( Count * 2 );
@@ -827,7 +854,7 @@
OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ClassDef_validate( table + ClassDef, valid );
OTV_LIMIT_CHECK( ClassSetCount * 2 );
@@ -875,7 +902,7 @@
OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
for ( count1 = GlyphCount; count1 > 0; count1-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
for ( ; Count > 0; Count-- )
{
@@ -916,7 +943,7 @@
OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ClassDef_validate( table + BacktrackClassDef, valid );
otv_ClassDef_validate( table + InputClassDef, valid );
@@ -966,7 +993,7 @@
OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
InputGlyphCount = FT_NEXT_USHORT( p );
@@ -975,7 +1002,7 @@
OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
for ( count1 = InputGlyphCount; count1 > 0; count1-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
LookaheadGlyphCount = FT_NEXT_USHORT( p );
@@ -984,7 +1011,7 @@
OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
count2 = FT_NEXT_USHORT( p );
--- a/src/otvalid/otvcommn.h
+++ b/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
/* */
/* OpenType common tables validation (specification). */
/* */
-/* Copyright 2004, 2005 by */
+/* Copyright 2004, 2005, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -215,7 +215,8 @@
FT_LOCAL( void )
otv_Coverage_validate( FT_Bytes table,
- OTV_Validator valid );
+ OTV_Validator valid,
+ FT_Int expected_count );
/* return first covered glyph */
FT_LOCAL( FT_UInt )
--- a/src/otvalid/otvgdef.c
+++ b/src/otvalid/otvgdef.c
@@ -61,7 +61,7 @@
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
- otv_Coverage_validate( Coverage, valid );
+ otv_Coverage_validate( Coverage, valid, GlyphCount );
if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
FT_INVALID_DATA;
--- a/src/otvalid/otvgpos.c
+++ b/src/otvalid/otvgpos.c
@@ -124,8 +124,8 @@
Array1 = FT_NEXT_USHORT( p );
Array2 = FT_NEXT_USHORT( p );
- otv_Coverage_validate( table + Coverage1, valid );
- otv_Coverage_validate( table + Coverage2, valid );
+ otv_Coverage_validate( table + Coverage1, valid, -1 );
+ otv_Coverage_validate( table + Coverage2, valid, -1 );
otv_MarkArray_validate( table + Array1, valid );
@@ -376,7 +376,7 @@
Coverage = FT_NEXT_USHORT( p );
ValueFormat = FT_NEXT_USHORT( p );
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
}
break;
@@ -395,7 +395,7 @@
len_value = otv_value_length( ValueFormat );
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, ValueCount );
OTV_LIMIT_CHECK( ValueCount * len_value );
@@ -498,7 +498,7 @@
OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, -1 );
OTV_LIMIT_CHECK( PairSetCount * 2 );
@@ -530,7 +530,7 @@
len_value1 = otv_value_length( ValueFormat1 );
len_value2 = otv_value_length( ValueFormat2 );
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, -1 );
otv_ClassDef_validate( table + ClassDef1, valid );
otv_ClassDef_validate( table + ClassDef2, valid );
@@ -605,7 +605,7 @@
OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
OTV_LIMIT_CHECK( EntryExitCount * 4 );
--- a/src/otvalid/otvgsub.c
+++ b/src/otvalid/otvgsub.c
@@ -68,15 +68,19 @@
Coverage = table + FT_NEXT_USHORT( p );
DeltaGlyphID = FT_NEXT_SHORT( p );
- otv_Coverage_validate( Coverage, valid );
+ otv_Coverage_validate( Coverage, valid, -1 );
idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
- if ( idx < 0 )
- FT_INVALID_DATA;
+ if ( idx < 0 ||
+ idx + DeltaGlyphID < 0 ||
+ (FT_UInt)idx + DeltaGlyphID >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
- if ( (FT_UInt)idx >= valid->glyph_count )
- FT_INVALID_DATA;
+ if ( (FT_UInt)idx >= valid->glyph_count ||
+ idx + DeltaGlyphID < 0 ||
+ (FT_UInt)idx + DeltaGlyphID >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
}
break;
@@ -91,7 +95,7 @@
OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, GlyphCount );
OTV_LIMIT_CHECK( GlyphCount * 2 );
@@ -98,7 +102,7 @@
/* Substitute */
for ( ; GlyphCount > 0; GlyphCount-- )
if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
- FT_INVALID_DATA;
+ FT_INVALID_GLYPH_ID;
}
break;
@@ -476,12 +480,12 @@
OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
- otv_Coverage_validate( Coverage, valid );
+ otv_Coverage_validate( Coverage, valid, -1 );
OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
LookaheadGlyphCount = FT_NEXT_USHORT( p );
@@ -490,7 +494,7 @@
OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
- otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid );
+ otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
GlyphCount = FT_NEXT_USHORT( p );
--- a/src/otvalid/otvmath.c
+++ b/src/otvalid/otvmath.c
@@ -55,12 +55,12 @@
OTV_NAME_ENTER( "MathConstants" );
- /* 57 constants, 52 have device tables */
- OTV_LIMIT_CHECK( 2 * ( 57 + 52 ) );
- table_size = 2 * ( 57 + 52 );
+ /* 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 < 52; ++i )
+ for ( i = 0; i < 51; ++i )
{
p += 2; /* skip the value */
OTV_OPTIONAL_OFFSET( DeviceTableOffset );
@@ -106,7 +106,7 @@
table_size = 4 + 4 * cnt;
OTV_SIZE_CHECK( Coverage );
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, cnt );
for ( i = 0; i < cnt; ++i )
{
@@ -194,7 +194,7 @@
table_size = 4 + 8 * cnt;
OTV_SIZE_CHECK( Coverage );
- otv_Coverage_validate( table + Coverage, valid );
+ otv_Coverage_validate( table + Coverage, valid, cnt );
for ( i = 0; i < cnt; ++i )
{
@@ -248,7 +248,7 @@
if ( ExtendedShapeCoverage ) {
OTV_NAME_ENTER( "ExtendedShapeCoverage" );
- otv_Coverage_validate( table + ExtendedShapeCoverage, valid );
+ otv_Coverage_validate( table + ExtendedShapeCoverage, valid, -1 );
OTV_EXIT;
}
@@ -273,6 +273,7 @@
{
FT_Bytes p = table;
FT_UInt pcnt, table_size;
+ FT_UInt i;
OTV_OPTIONAL_TABLE( DeviceTableOffset );
@@ -292,6 +293,17 @@
if ( DeviceTableOffset )
otv_Device_validate( table + DeviceTableOffset, valid );
+ for ( i = 0; i < pcnt; ++i )
+ {
+ FT_UInt gid;
+
+
+ gid = FT_NEXT_USHORT( p );
+ if ( gid >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
+ p += 2*4; /* skip the Start, End, Full, and Flags fields */
+ }
+
/* OTV_EXIT; */
}
@@ -302,6 +314,7 @@
{
FT_Bytes p = table;
FT_UInt vcnt, table_size;
+ FT_UInt i;
OTV_OPTIONAL_TABLE( GlyphAssembly );
@@ -316,6 +329,17 @@
OTV_LIMIT_CHECK( 4 * vcnt );
table_size = 4 + 4 * vcnt;
+ for ( i = 0; i < vcnt; ++i )
+ {
+ FT_UInt gid;
+
+
+ gid = FT_NEXT_USHORT( p );
+ if ( gid >= valid->glyph_count )
+ FT_INVALID_GLYPH_ID;
+ p += 2; /* skip the size */
+ }
+
OTV_SIZE_CHECK( GlyphAssembly );
if ( GlyphAssembly )
otv_GlyphAssembly_validate( table+GlyphAssembly, valid );
@@ -351,11 +375,11 @@
OTV_SIZE_CHECK( VCoverage );
if ( VCoverage )
- otv_Coverage_validate( table + VCoverage, valid );
+ otv_Coverage_validate( table + VCoverage, valid, vcnt );
OTV_SIZE_CHECK( HCoverage );
if ( HCoverage )
- otv_Coverage_validate( table + HCoverage, valid );
+ otv_Coverage_validate( table + HCoverage, valid, hcnt );
for ( i = 0; i < vcnt; ++i )
{