aboutsummaryrefslogtreecommitdiff
path: root/freetype/src/gxvalid
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-07-18 08:30:47 +0200
committermarha <marha@users.sourceforge.net>2011-07-18 08:30:47 +0200
commitd8e3f99cdf46297afeb26fe15ad30f7c6de8ee7c (patch)
tree199776414c3aa9aab0a35c1d16d38c7a072d6665 /freetype/src/gxvalid
parent7723537ddbe5dd4070f2bebbd4e0c93be3244b18 (diff)
downloadvcxsrv-d8e3f99cdf46297afeb26fe15ad30f7c6de8ee7c.tar.gz
vcxsrv-d8e3f99cdf46297afeb26fe15ad30f7c6de8ee7c.tar.bz2
vcxsrv-d8e3f99cdf46297afeb26fe15ad30f7c6de8ee7c.zip
Switched to freetype 2.4.5
Diffstat (limited to 'freetype/src/gxvalid')
-rw-r--r--freetype/src/gxvalid/gxvcommn.c45
-rw-r--r--freetype/src/gxvalid/gxvcommn.h16
-rw-r--r--freetype/src/gxvalid/gxvfeat.c25
-rw-r--r--freetype/src/gxvalid/gxvjust.c107
-rw-r--r--freetype/src/gxvalid/gxvkern.c66
-rw-r--r--freetype/src/gxvalid/gxvmort.c23
-rw-r--r--freetype/src/gxvalid/gxvmort0.c16
-rw-r--r--freetype/src/gxvalid/gxvmort1.c27
-rw-r--r--freetype/src/gxvalid/gxvmort2.c37
-rw-r--r--freetype/src/gxvalid/gxvmort5.c9
-rw-r--r--freetype/src/gxvalid/gxvmorx.c15
-rw-r--r--freetype/src/gxvalid/gxvmorx0.c8
-rw-r--r--freetype/src/gxvalid/gxvmorx1.c7
-rw-r--r--freetype/src/gxvalid/gxvmorx2.c40
-rw-r--r--freetype/src/gxvalid/gxvmorx5.c8
-rw-r--r--freetype/src/gxvalid/gxvprop.c30
-rw-r--r--freetype/src/gxvalid/gxvtrak.c19
17 files changed, 400 insertions, 98 deletions
diff --git a/freetype/src/gxvalid/gxvcommn.c b/freetype/src/gxvalid/gxvcommn.c
index 211f97201..d3c48d4ea 100644
--- a/freetype/src/gxvalid/gxvcommn.c
+++ b/freetype/src/gxvalid/gxvcommn.c
@@ -304,8 +304,7 @@
binSrchHeader->unitSize, binSrchHeader->nUnits,
searchRange, entrySelector, rangeShift ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
}
@@ -442,8 +441,7 @@
{
GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
i, valid->face->num_glyphs ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
break;
}
@@ -531,8 +529,7 @@
GXV_TRACE(( "reverse ordered segment specification:"
" lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
unit, lastGlyph, unit - 1 , gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
if ( lastGlyph < firstGlyph )
@@ -540,8 +537,7 @@
GXV_TRACE(( "reverse ordered range specification at unit %d:",
" lastGlyph %d < firstGlyph %d ",
unit, lastGlyph, firstGlyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
if ( valid->root->level == FT_VALIDATE_TIGHT )
continue; /* ftxvalidator silently skips such an entry */
@@ -604,8 +600,7 @@
GXV_TRACE(( "reverse ordered segment specification:"
" lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
unit, lastGlyph, unit - 1 , gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
if ( lastGlyph < firstGlyph )
@@ -613,8 +608,7 @@
GXV_TRACE(( "reverse ordered range specification at unit %d:",
" lastGlyph %d < firstGlyph %d ",
unit, lastGlyph, firstGlyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
if ( valid->root->level == FT_VALIDATE_TIGHT )
continue; /* ftxvalidator silently skips such an entry */
@@ -705,8 +699,7 @@
{
GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
glyph, prev_glyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
prev_glyph = glyph;
@@ -834,8 +827,7 @@
{
GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
face->num_glyphs, gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
return 0;
@@ -1101,8 +1093,7 @@
if ( ( maxEntry + 1 ) * entrySize > *length_p )
{
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_TOO_SHORT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_TOO_SHORT );
/* ftxvalidator and FontValidator both warn and continue */
maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
@@ -1126,8 +1117,7 @@
{
GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
newState ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
continue;
}
@@ -1135,8 +1125,7 @@
{
GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
newState, 1 + maxClassID ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
continue;
}
@@ -1173,8 +1162,7 @@
break;
default:
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_FORMAT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
goto Exit;
}
@@ -1503,8 +1491,7 @@
{
GXV_TRACE(( " newState index 0x%04x points out of stateArray\n",
newState_idx ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
@@ -1513,8 +1500,7 @@
FT_TRACE4(( "-> new state = %d (supposed)\n"
"but newState index 0x%04x is not aligned to %d-classes\n",
state, newState_idx, 1 + maxClassID ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
@@ -1548,8 +1534,7 @@
break;
default:
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_FORMAT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
goto Exit;
}
diff --git a/freetype/src/gxvalid/gxvcommn.h b/freetype/src/gxvalid/gxvcommn.h
index 404c07ffa..35c043dbd 100644
--- a/freetype/src/gxvalid/gxvcommn.h
+++ b/freetype/src/gxvalid/gxvcommn.h
@@ -51,6 +51,19 @@
FT_BEGIN_HEADER
+ /* some variables are not evaluated or only used in trace */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+#define GXV_LOAD_TRACE_VARS
+#else
+#undef GXV_LOAD_TRACE_VARS
+#endif
+
+#undef GXV_LOAD_UNUSED_VARS /* debug purpose */
+
+#define IS_PARANOID_VALIDATION ( valid->root->level >= FT_VALIDATE_PARANOID )
+#define GXV_SET_ERR_IF_PARANOID( err ) { if ( IS_PARANOID_VALIDATION ) ( err ); }
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -234,6 +247,9 @@ FT_BEGIN_HEADER
GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans;
FT_Bytes lookuptbl_head;
+ FT_UShort min_gid;
+ FT_UShort max_gid;
+
GXV_StateTable_ValidatorRec statetable;
GXV_XStateTable_ValidatorRec xstatetable;
diff --git a/freetype/src/gxvalid/gxvfeat.c b/freetype/src/gxvalid/gxvfeat.c
index 002fec6d6..46792bbf9 100644
--- a/freetype/src/gxvalid/gxvfeat.c
+++ b/freetype/src/gxvalid/gxvfeat.c
@@ -92,8 +92,7 @@
{
GXV_TRACE(( "feature number %d is out of range %d\n",
feature, gxv_feat_registry_length ));
- if ( valid->root->level == FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
goto Exit;
}
@@ -101,8 +100,7 @@
{
GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
feature ));
- if ( valid->root->level == FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
goto Exit;
}
@@ -222,9 +220,8 @@
if ( settingTable < reserved_size )
FT_INVALID_OFFSET;
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
- FT_INVALID_DATA;
+ if ( ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS );
if ( exclusive )
@@ -252,9 +249,8 @@
{
gxv_feat_setting_validate( p, limit, exclusive, valid );
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
- FT_INVALID_FORMAT;
+ if ( (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
last_setting = (FT_Int)GXV_FEAT_DATA( setting );
/* setting + nameIndex */
@@ -312,8 +308,8 @@
featureNameCount = FT_NEXT_USHORT( p );
GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount ));
- if ( valid->root->level != FT_VALIDATE_PARANOID )
- p += 6; /* skip (none) and (none) */
+ if ( !( IS_PARANOID_VALIDATION ) )
+ p += 6; /* skip (none) and (none) */
else
{
if ( FT_NEXT_USHORT( p ) != 0 )
@@ -329,9 +325,8 @@
{
gxv_feat_name_validate( p, limit, valid );
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
- FT_INVALID_FORMAT;
+ if ( (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
last_feature = GXV_FEAT_DATA( feature );
p += 2 + 2 + 4 + 2 + 2;
diff --git a/freetype/src/gxvalid/gxvjust.c b/freetype/src/gxvalid/gxvjust.c
index e14f946f2..7816e0b7f 100644
--- a/freetype/src/gxvalid/gxvjust.c
+++ b/freetype/src/gxvalid/gxvjust.c
@@ -65,6 +65,22 @@
#define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
+ /* GX just table does not define their subset of GID */
+ static void
+ gxv_just_check_max_gid( FT_UShort gid,
+ const FT_String* msg_tag,
+ GXV_Validator valid )
+ {
+ if ( gid < valid->face->num_glyphs )
+ return;
+
+ GXV_TRACE(( "just table includes too large %s"
+ " GID=%d > %d (in maxp)\n",
+ msg_tag, gid, valid->face->num_glyphs ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
+ }
+
+
static void
gxv_just_wdp_entry_validate( FT_Bytes table,
FT_Bytes limit,
@@ -72,24 +88,37 @@
{
FT_Bytes p = table;
FT_ULong justClass;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Fixed beforeGrowLimit;
FT_Fixed beforeShrinkGrowLimit;
FT_Fixed afterGrowLimit;
FT_Fixed afterShrinkGrowLimit;
FT_UShort growFlags;
FT_UShort shrinkFlags;
+#endif
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
justClass = FT_NEXT_ULONG( p );
+#ifndef GXV_LOAD_UNUSED_VARS
+ p += 4 + 4 + 4 + 4 + 2 + 2;
+#else
beforeGrowLimit = FT_NEXT_ULONG( p );
beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
afterGrowLimit = FT_NEXT_ULONG( p );
afterShrinkGrowLimit = FT_NEXT_ULONG( p );
growFlags = FT_NEXT_USHORT( p );
shrinkFlags = FT_NEXT_USHORT( p );
+#endif
- /* TODO: decode flags for human readability */
+ /* According to Apple spec, only 7bits in justClass is used */
+ if ( ( justClass & 0xFFFFFF80 ) != 0 )
+ {
+ GXV_TRACE(( "just table includes non-zero value"
+ " in unused justClass higher bits"
+ " of WidthDeltaPair" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
valid->subtable_length = p - table;
}
@@ -153,8 +182,9 @@
FT_Fixed lowerLimit;
FT_Fixed upperLimit;
-
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort order;
+#endif
FT_UShort decomposedCount;
FT_UInt i;
@@ -163,9 +193,20 @@
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
lowerLimit = FT_NEXT_ULONG( p );
upperLimit = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
order = FT_NEXT_USHORT( p );
+#else
+ p += 2;
+#endif
decomposedCount = FT_NEXT_USHORT( p );
+ if ( lowerLimit >= upperLimit )
+ {
+ GXV_TRACE(( "just table includes invalid range spec:"
+ " lowerLimit(%d) > upperLimit(%d)\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
for ( i = 0; i < decomposedCount; i++ )
{
FT_UShort glyphs;
@@ -173,6 +214,7 @@
GXV_LIMIT_CHECK( 2 );
glyphs = FT_NEXT_USHORT( p );
+ gxv_just_check_max_gid( glyphs, "type0:glyphs", valid );
}
valid->subtable_length = p - table;
@@ -191,6 +233,8 @@
GXV_LIMIT_CHECK( 2 );
addGlyph = FT_NEXT_USHORT( p );
+ gxv_just_check_max_gid( addGlyph, "type1:addGlyph", valid );
+
valid->subtable_length = p - table;
}
@@ -201,16 +245,27 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
+#endif
FT_UShort addGlyph;
FT_UShort substGlyph;
GXV_LIMIT_CHECK( 4 + 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
substThreshhold = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
addGlyph = FT_NEXT_USHORT( p );
substGlyph = FT_NEXT_USHORT( p );
+ if ( addGlyph != 0xFFFF )
+ gxv_just_check_max_gid( addGlyph, "type2:addGlyph", valid );
+
+ gxv_just_check_max_gid( substGlyph, "type2:substGlyph", valid );
+
valid->subtable_length = p - table;
}
@@ -234,6 +289,21 @@
maximumLimit = FT_NEXT_ULONG( p );
valid->subtable_length = p - table;
+
+ if ( variantsAxis != 0x64756374 ) /* 'duct' */
+ GXV_TRACE(( "variantsAxis 0x%08x is non default value",
+ variantsAxis ));
+
+ if ( minimumLimit > noStretchValue )
+ GXV_TRACE(( "type4:minimumLimit 0x%08x > noStretchValue 0x%08x\n",
+ minimumLimit, noStretchValue ));
+ else if ( noStretchValue > maximumLimit )
+ GXV_TRACE(( "type4:noStretchValue 0x%08x > maximumLimit 0x%08x\n",
+ noStretchValue, maximumLimit ));
+ else if ( !IS_PARANOID_VALIDATION )
+ return;
+
+ FT_INVALID_DATA;
}
@@ -251,6 +321,11 @@
flags = FT_NEXT_USHORT( p );
glyph = FT_NEXT_USHORT( p );
+ if ( flags )
+ GXV_TRACE(( "type5: nonzero value 0x%04x in unused flags\n",
+ flags ));
+ gxv_just_check_max_gid( glyph, "type5:glyph", valid );
+
valid->subtable_length = p - table;
}
@@ -274,6 +349,10 @@
actionType = FT_NEXT_USHORT( p );
actionLength = FT_NEXT_ULONG( p );
+ /* actionClass is related with justClass using 7bit only */
+ if ( ( actionClass & 0xFF80 ) != 0 )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+
if ( actionType == 0 )
gxv_just_actSubrecord_type0_validate( p, limit, valid );
else if ( actionType == 1 )
@@ -389,10 +468,13 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
+ /* TODO: validate markClass & currentClass */
FT_UShort setMark;
FT_UShort dontAdvance;
FT_UShort markClass;
FT_UShort currentClass;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
@@ -400,13 +482,14 @@
FT_UNUSED( limit );
FT_UNUSED( valid );
-
+#ifndef GXV_LOAD_UNUSED_VARS
+ FT_UNUSED( flags );
+#else
setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
markClass = (FT_UShort)( ( flags >> 7 ) & 0x7F );
currentClass = (FT_UShort)( flags & 0x7F );
-
- /* TODO: validate markClass & currentClass */
+#endif
}
@@ -428,9 +511,15 @@
coverage = FT_NEXT_USHORT( p );
subFeatureFlags = FT_NEXT_ULONG( p );
- GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
- coverage,
- ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
+ GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s) ", coverage ));
+ if ( ( coverage & 0x4000 ) == 0 )
+ GXV_TRACE(( "ascending\n" ));
+ else
+ GXV_TRACE(( "descending\n" ));
+
+ if ( subFeatureFlags )
+ GXV_TRACE(( " justClassTable: nonzero value (0x%08x)"
+ " in unused subFeatureFlags\n", subFeatureFlags ));
valid->statetable.optdata = NULL;
valid->statetable.optdata_load_func = NULL;
@@ -557,7 +646,6 @@
{
FT_Bytes p = table;
FT_Bytes limit = 0;
- FT_Offset table_size;
GXV_ValidatorRec validrec;
GXV_Validator valid = &validrec;
@@ -582,7 +670,6 @@
GXV_INIT;
limit = valid->root->limit;
- table_size = limit - table;
GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
version = FT_NEXT_ULONG( p );
diff --git a/freetype/src/gxvalid/gxvkern.c b/freetype/src/gxvalid/gxvkern.c
index 2137db842..0ec978f7b 100644
--- a/freetype/src/gxvalid/gxvkern.c
+++ b/freetype/src/gxvalid/gxvkern.c
@@ -127,7 +127,9 @@
{
FT_UShort gid_left;
FT_UShort gid_right;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Short kernValue;
+#endif
/* left */
@@ -156,7 +158,11 @@
FT_INVALID_DATA;
/* skip the kern value */
+#ifdef GXV_LOAD_UNUSED_VARS
kernValue = FT_NEXT_SHORT( p );
+#else
+ p += 2;
+#endif
}
GXV_EXIT;
@@ -261,18 +267,24 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort push;
FT_UShort dontAdvance;
+#endif
FT_UShort valueOffset;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort kernAction;
FT_UShort kernValue;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
+#ifdef GXV_LOAD_UNUSED_VARS
push = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
valueOffset = (FT_UShort)( flags & 0x3FFF );
{
@@ -288,8 +300,12 @@
limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
GXV_LIMIT_CHECK( 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
kernAction = FT_NEXT_USHORT( p );
kernValue = FT_NEXT_USHORT( p );
+#else
+ p += 4;
+#endif
}
}
@@ -475,10 +491,12 @@
{
GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
valid->face->num_glyphs, glyphCount ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
+ if ( flags != 0 )
+ GXV_TRACE(( "kern subtable fmt3 has nonzero value"
+ " (%d) in unused flag\n", flags ));
/*
* just skip kernValue[kernValueCount]
*/
@@ -545,20 +563,24 @@
GXV_Validator valid )
{
/* new Apple-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool kernVertical;
FT_Bool kernCrossStream;
FT_Bool kernVariation;
+#endif
FT_UNUSED( valid );
/* reserved bits = 0 */
if ( coverage & 0x1FFC )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 );
kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 );
+#endif
*format = (FT_UShort)( coverage & 0x0003 );
@@ -568,7 +590,7 @@
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -578,20 +600,24 @@
GXV_Validator valid )
{
/* classic Apple-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool horizontal;
FT_Bool cross_stream;
+#endif
/* check expected flags, but don't check if MS-dialect is impossible */
if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
- return 0;
+ return FALSE;
/* reserved bits = 0 */
if ( coverage & 0x02FC )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
horizontal = FT_BOOL( ( coverage >> 15 ) & 1 );
cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
+#endif
*format = (FT_UShort)( coverage & 0x0003 );
@@ -601,11 +627,11 @@
/* format 1 requires GX State Machine, too new for classic */
if ( *format == 1 )
- return 0;
+ return FALSE;
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -615,22 +641,26 @@
GXV_Validator valid )
{
/* classic Microsoft-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool horizontal;
FT_Bool minimum;
FT_Bool cross_stream;
FT_Bool override;
+#endif
FT_UNUSED( valid );
/* reserved bits = 0 */
if ( coverage & 0xFDF0 )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
horizontal = FT_BOOL( coverage & 1 );
minimum = FT_BOOL( ( coverage >> 1 ) & 1 );
cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
override = FT_BOOL( ( coverage >> 3 ) & 1 );
+#endif
*format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
@@ -643,7 +673,7 @@
GXV_TRACE((
"kerning values in Microsoft format 2 subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -714,10 +744,14 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort version = 0; /* MS only: subtable version, unused */
+#endif
FT_ULong length; /* MS: 16bit, Apple: 32bit*/
FT_UShort coverage;
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort tupleIndex = 0; /* Apple only */
+#endif
FT_UShort u16[2];
FT_UShort format = 255; /* subtable format */
@@ -732,23 +766,35 @@
switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
{
case KERN_DIALECT_MS:
+#ifdef GXV_LOAD_TRACE_VARS
version = u16[0];
+#endif
length = u16[1];
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = 0;
+#endif
GXV_TRACE(( "Subtable version = %d\n", version ));
GXV_TRACE(( "Subtable length = %d\n", length ));
break;
case KERN_DIALECT_APPLE:
+#ifdef GXV_LOAD_TRACE_VARS
version = 0;
+#endif
length = ( u16[0] << 16 ) + u16[1];
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = 0;
+#endif
GXV_TRACE(( "Subtable length = %d\n", length ));
if ( KERN_IS_NEW( valid ) )
{
GXV_LIMIT_CHECK( 2 );
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = FT_NEXT_USHORT( p );
+#else
+ p += 2;
+#endif
GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
}
break;
diff --git a/freetype/src/gxvalid/gxvmort.c b/freetype/src/gxvalid/gxvmort.c
index 0aa066339..465462a05 100644
--- a/freetype/src/gxvalid/gxvmort.c
+++ b/freetype/src/gxvalid/gxvmort.c
@@ -47,16 +47,14 @@
GXV_TRACE(( "featureType %d is out of registered range, "
"setting %d is unchecked\n",
f->featureType, f->featureSetting ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else if ( !gxv_feat_registry[f->featureType].existence )
{
GXV_TRACE(( "featureType %d is within registered area "
"but undefined, setting %d is unchecked\n",
f->featureType, f->featureSetting ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else
{
@@ -74,8 +72,7 @@
if ( f->featureSetting > nSettings_max )
{
GXV_TRACE(( "out of defined range %d", nSettings_max ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
GXV_TRACE(( "\n" ));
}
@@ -176,7 +173,9 @@
{
FT_UShort length;
FT_UShort coverage;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong subFeatureFlags;
+#endif
FT_UInt type;
FT_UInt rest;
@@ -184,7 +183,11 @@
GXV_LIMIT_CHECK( 2 + 2 + 4 );
length = FT_NEXT_USHORT( p );
coverage = FT_NEXT_USHORT( p );
+#ifdef GXV_LOAD_UNUSED_VARS
subFeatureFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
i + 1, nSubtables, length ));
@@ -204,6 +207,7 @@
func( p, p + rest, valid );
p += rest;
+ /* TODO: validate subFeatureFlags */
}
valid->subtable_length = p - table;
@@ -218,7 +222,9 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong defaultFlags;
+#endif
FT_ULong chainLength;
FT_UShort nFeatureFlags;
FT_UShort nSubtables;
@@ -227,7 +233,11 @@
GXV_NAME_ENTER( "mort chain header" );
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
defaultFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
chainLength = FT_NEXT_ULONG( p );
nFeatureFlags = FT_NEXT_USHORT( p );
nSubtables = FT_NEXT_USHORT( p );
@@ -238,6 +248,7 @@
gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
valid->subtable_length = chainLength;
+ /* TODO: validate defaultFlags */
GXV_EXIT;
}
diff --git a/freetype/src/gxvalid/gxvmort0.c b/freetype/src/gxvalid/gxvmort0.c
index 0453062f6..b136ceda2 100644
--- a/freetype/src/gxvalid/gxvmort0.c
+++ b/freetype/src/gxvalid/gxvmort0.c
@@ -98,10 +98,24 @@
GXV_TRACE(( " %02d", verb ));
GXV_TRACE(( " %s\n", GXV_Mort_IndicScript_Msg[verb] ));
+ if ( markFirst > 0 && markLast > 0 )
+ {
+ GXV_TRACE(( " [odd] a glyph is marked as the first and last"
+ " in Indic rearrangement\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
+ if ( markFirst > 0 && dontAdvance > 0 )
+ {
+ GXV_TRACE(( " [odd] the first glyph is marked as dontAdvance"
+ " in Indic rearrangement\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else
GXV_TRACE(( "\n" ));
diff --git a/freetype/src/gxvalid/gxvmort1.c b/freetype/src/gxvalid/gxvmort1.c
index 696d85032..1c17a5d92 100644
--- a/freetype/src/gxvalid/gxvmort1.c
+++ b/freetype/src/gxvalid/gxvmort1.c
@@ -106,8 +106,6 @@
{
FT_UShort substTable;
FT_UShort substTable_limit;
- FT_UShort min_gid;
- FT_UShort max_gid;
FT_UNUSED( tag );
FT_UNUSED( state );
@@ -121,9 +119,10 @@
((GXV_mort_subtable_type1_StateOptRec *)
(valid->statetable.optdata))->substitutionTable_length );
- min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
- max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
- max_gid = (FT_UShort)( FT_MAX( max_gid, valid->face->num_glyphs ) );
+ valid->min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
+ valid->max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
+ valid->max_gid = (FT_UShort)( FT_MAX( valid->max_gid,
+ valid->face->num_glyphs ) );
/* XXX: check range? */
@@ -140,8 +139,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setMark;
FT_UShort dontAdvance;
+#endif
FT_UShort reserved;
FT_Short markOffset;
FT_Short currentOffset;
@@ -150,8 +151,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = (FT_UShort)( flags >> 15 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
reserved = (FT_Short)( flags & 0x3FFF );
markOffset = (FT_Short)( glyphOffset_p->ul >> 16 );
@@ -160,8 +163,7 @@
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
@@ -200,13 +202,12 @@
if ( dst_gid >= 0xFFFFU )
continue;
- if ( dst_gid > valid->face->num_glyphs )
+ if ( dst_gid < valid->min_gid || valid->max_gid < dst_gid )
{
- GXV_TRACE(( "substTable include too large gid[%d]=%d >"
- " max defined gid #%d\n",
- i, dst_gid, valid->face->num_glyphs ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_TRACE(( "substTable include a strange gid[%d]=%d >"
+ " out of define range (%d..%d)\n",
+ i, dst_gid, valid->min_gid, valid->max_gid ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
diff --git a/freetype/src/gxvalid/gxvmort2.c b/freetype/src/gxvalid/gxvmort2.c
index 6f77cf39c..9e08fb792 100644
--- a/freetype/src/gxvalid/gxvmort2.c
+++ b/freetype/src/gxvalid/gxvmort2.c
@@ -155,8 +155,7 @@
ligActionOffset, lat_base - p ));
/* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
else if ( lat_limit < p )
{
@@ -164,23 +163,46 @@
ligActionOffset, p - lat_limit ));
/* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ 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 );
+ }
}
}
@@ -194,8 +216,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setComponent;
FT_UShort dontAdvance;
+#endif
FT_UShort offset;
FT_UNUSED( state );
@@ -203,8 +227,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
offset = (FT_UShort)( flags & 0x3FFFU );
@@ -237,6 +263,9 @@
GXV_LIMIT_CHECK( 2 );
lig_gid = FT_NEXT_USHORT( p );
+
+ if ( valid->face->num_glyphs < lig_gid )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
GXV_EXIT;
diff --git a/freetype/src/gxvalid/gxvmort5.c b/freetype/src/gxvalid/gxvmort5.c
index ec0bcb634..32cfb0363 100644
--- a/freetype/src/gxvalid/gxvmort5.c
+++ b/freetype/src/gxvalid/gxvmort5.c
@@ -121,6 +121,9 @@
offset < optdata->entryTable + *(optdata->entryTable_length_p) )
GXV_TRACE(( " offset runs into EntryTable" ));
+#ifndef GXV_LOAD_TRACE_VARS
+ GXV_LIMIT_CHECK( count * 2 );
+#else
while ( p < table + offset + ( count * 2 ) )
{
FT_UShort insert_glyphID;
@@ -130,8 +133,8 @@
insert_glyphID = FT_NEXT_USHORT( p );
GXV_TRACE(( " 0x%04x", insert_glyphID ));
}
-
GXV_TRACE(( "\n" ));
+#endif
}
@@ -144,12 +147,14 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Bool setMark;
FT_Bool dontAdvance;
FT_Bool currentIsKashidaLike;
FT_Bool markedIsKashidaLike;
FT_Bool currentInsertBefore;
FT_Bool markedInsertBefore;
+#endif
FT_Byte currentInsertCount;
FT_Byte markedInsertCount;
FT_UShort currentInsertList;
@@ -158,12 +163,14 @@
FT_UNUSED( state );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = FT_BOOL( ( flags >> 15 ) & 1 );
dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+#endif
currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
markedInsertCount = (FT_Byte)( flags & 0x001F );
diff --git a/freetype/src/gxvalid/gxvmorx.c b/freetype/src/gxvalid/gxvmorx.c
index f8ba5b985..4b1dd0050 100644
--- a/freetype/src/gxvalid/gxvmorx.c
+++ b/freetype/src/gxvalid/gxvmorx.c
@@ -68,7 +68,9 @@
{
FT_ULong length;
FT_ULong coverage;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong subFeatureFlags;
+#endif
FT_ULong type;
FT_ULong rest;
@@ -76,7 +78,11 @@
GXV_LIMIT_CHECK( 4 + 4 + 4 );
length = FT_NEXT_ULONG( p );
coverage = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
subFeatureFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
i + 1, nSubtables, length ));
@@ -97,6 +103,7 @@
func( p, p + rest, valid );
+ /* TODO: subFeatureFlags should be unique in a table? */
p += rest;
}
@@ -112,7 +119,9 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong defaultFlags;
+#endif
FT_ULong chainLength;
FT_ULong nFeatureFlags;
FT_ULong nSubtables;
@@ -121,7 +130,11 @@
GXV_NAME_ENTER( "morx chain header" );
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
+#ifdef GXV_LOAD_UNUSED_VARS
defaultFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
chainLength = FT_NEXT_ULONG( p );
nFeatureFlags = FT_NEXT_ULONG( p );
nSubtables = FT_NEXT_ULONG( p );
@@ -138,6 +151,8 @@
valid->subtable_length = chainLength;
+ /* TODO: defaultFlags should be compared with the flags in tables */
+
GXV_EXIT;
}
diff --git a/freetype/src/gxvalid/gxvmorx0.c b/freetype/src/gxvalid/gxvmorx0.c
index 0159c5aef..6a736c177 100644
--- a/freetype/src/gxvalid/gxvmorx0.c
+++ b/freetype/src/gxvalid/gxvmorx0.c
@@ -47,11 +47,15 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort markFirst;
FT_UShort dontAdvance;
FT_UShort markLast;
+#endif
FT_UShort reserved;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort verb;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
@@ -59,12 +63,16 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
markFirst = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
markLast = (FT_UShort)( ( flags >> 13 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x1FF0 );
+#ifdef GXV_LOAD_UNUSED_VARS
verb = (FT_UShort)( flags & 0x000F );
+#endif
if ( 0 < reserved )
{
diff --git a/freetype/src/gxvalid/gxvmorx1.c b/freetype/src/gxvalid/gxvmorx1.c
index e1c162fa0..ce0009a16 100644
--- a/freetype/src/gxvalid/gxvmorx1.c
+++ b/freetype/src/gxvalid/gxvmorx1.c
@@ -108,8 +108,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort setMark;
FT_UShort dontAdvance;
+#endif
FT_UShort reserved;
FT_Short markIndex;
FT_Short currentIndex;
@@ -122,8 +124,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_TRACE_VARS
setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x3FFF );
@@ -136,8 +140,7 @@
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
GXV_TRACE(( "markIndex = %d, currentIndex = %d\n",
diff --git a/freetype/src/gxvalid/gxvmorx2.c b/freetype/src/gxvalid/gxvmorx2.c
index b4bb3353f..bc18c6b8a 100644
--- a/freetype/src/gxvalid/gxvmorx2.c
+++ b/freetype/src/gxvalid/gxvmorx2.c
@@ -168,16 +168,50 @@
{
/* 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
offset = lig_action & 0x3FFFFFFFUL;
+
+ /* this offset is 30-bit signed value to add to GID */
+ /* it is different from the location offset in mort */
+ if ( ( offset & 0x3FFF0000UL ) == 0x3FFF0000UL )
+ {
+ if ( offset + valid->face->num_glyphs > 0x40000000UL )
+ return;
+
+ GXV_TRACE(( "ligature action table includes"
+ " too negative offset moving all GID"
+ " below defined range: 0x%04x\n",
+ offset & 0xFFFFU ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ }
+ else if ( ( offset & 0x3FFF0000UL ) == 0x0000000UL )
+ {
+ if ( offset + valid->face->num_glyphs < 0 )
+ return;
+
+ GXV_TRACE(( "ligature action table includes"
+ " too large offset moving all GID"
+ " over defined range: 0x%04x\n",
+ offset & 0xFFFFU ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ }
+
+ GXV_TRACE(( "ligature action table includes"
+ " invalid offset to add to 16-bit GID:"
+ " 0x%08x\n", offset ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
}
@@ -191,9 +225,11 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setComponent;
FT_UShort dontAdvance;
FT_UShort performAction;
+#endif
FT_UShort reserved;
FT_UShort ligActionIndex;
@@ -201,9 +237,11 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
performAction = (FT_UShort)( ( flags >> 13 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x1FFF );
ligActionIndex = glyphOffset_p->u;
@@ -241,6 +279,8 @@
GXV_LIMIT_CHECK( 2 );
lig_gid = FT_NEXT_USHORT( p );
+ if ( lig_gid < valid->face->num_glyphs )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
diff --git a/freetype/src/gxvalid/gxvmorx5.c b/freetype/src/gxvalid/gxvmorx5.c
index 5e3a16437..d8cf70079 100644
--- a/freetype/src/gxvalid/gxvmorx5.c
+++ b/freetype/src/gxvalid/gxvmorx5.c
@@ -118,6 +118,9 @@
FT_Bytes p = table + table_index * 2;
+#ifndef GXV_LOAD_TRACE_VARS
+ GXV_LIMIT_CHECK( count * 2 );
+#else
while ( p < table + count * 2 + table_index * 2 )
{
FT_UShort insert_glyphID;
@@ -129,6 +132,7 @@
}
GXV_TRACE(( "\n" ));
+#endif
}
@@ -141,12 +145,14 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Bool setMark;
FT_Bool dontAdvance;
FT_Bool currentIsKashidaLike;
FT_Bool markedIsKashidaLike;
FT_Bool currentInsertBefore;
FT_Bool markedInsertBefore;
+#endif
FT_Byte currentInsertCount;
FT_Byte markedInsertCount;
FT_Byte currentInsertList;
@@ -155,12 +161,14 @@
FT_UNUSED( state );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = FT_BOOL( ( flags >> 15 ) & 1 );
dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+#endif
currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
markedInsertCount = (FT_Byte)( flags & 0x001F );
diff --git a/freetype/src/gxvalid/gxvprop.c b/freetype/src/gxvalid/gxvprop.c
index 66c3ab740..54777271a 100644
--- a/freetype/src/gxvalid/gxvprop.c
+++ b/freetype/src/gxvalid/gxvprop.c
@@ -96,7 +96,10 @@
if ( glyph->advance.x != (FT_Pos)0 ||
glyph->advance.y != (FT_Pos)0 )
+ {
+ GXV_TRACE(( " found non-zero advance in zero-advance glyph\n" ));
FT_INVALID_DATA;
+ }
GXV_EXIT;
}
@@ -119,7 +122,10 @@
offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET );
if ( offset == 0 )
- FT_INVALID_DATA;
+ {
+ GXV_TRACE(( " found zero offset to property\n" ));
+ FT_INVALID_OFFSET;
+ }
complement = (char)( offset >> 8 );
if ( complement & 0x08 )
@@ -131,7 +137,10 @@
/* The gid for complement must be greater than 0 */
if ( glyph <= complement )
+ {
+ GXV_TRACE(( " found non-positive glyph complement\n" ));
FT_INVALID_DATA;
+ }
}
else
{
@@ -150,18 +159,27 @@
if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
{
if ( GXV_PROP_DATA( version ) == 0x00010000UL )
+ {
+ GXV_TRACE(( " found older version (1.0) in new version table\n" ));
FT_INVALID_DATA;
+ }
}
if ( property & GXV_PROP_RESERVED )
+ {
+ GXV_TRACE(( " found non-zero bits in reserved bits\n" ));
FT_INVALID_DATA;
+ }
if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
{
/* TODO: Too restricted. Use the validation level. */
if ( GXV_PROP_DATA( version ) == 0x00010000UL ||
GXV_PROP_DATA( version ) == 0x00020000UL )
+ {
+ GXV_TRACE(( " found too old version in directionality class\n" ));
FT_INVALID_DATA;
+ }
}
}
@@ -264,16 +282,26 @@
format = FT_NEXT_USHORT( p );
defaultProp = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " version 0x%08x\n", version ));
+ GXV_TRACE(( " format 0x%04x\n", format ));
+ GXV_TRACE(( " defaultProp 0x%04x\n", defaultProp ));
+
/* only versions 1.0, 2.0, 3.0 are defined (1996) */
if ( version != 0x00010000UL &&
version != 0x00020000UL &&
version != 0x00030000UL )
+ {
+ GXV_TRACE(( " found unknown version\n" ));
FT_INVALID_FORMAT;
+ }
/* only formats 0x0000, 0x0001 are defined (1996) */
if ( format > 1 )
+ {
+ GXV_TRACE(( " found unknown format\n" ));
FT_INVALID_FORMAT;
+ }
gxv_prop_property_validate( defaultProp, 0, valid );
diff --git a/freetype/src/gxvalid/gxvtrak.c b/freetype/src/gxvalid/gxvtrak.c
index df3fd15c0..11fbd7ccf 100644
--- a/freetype/src/gxvalid/gxvtrak.c
+++ b/freetype/src/gxvalid/gxvtrak.c
@@ -97,10 +97,10 @@
{
FT_Bytes p = table;
- FT_Fixed track;
+ FT_Fixed track, t;
FT_UShort nameIndex;
FT_UShort offset;
- FT_UShort i;
+ FT_UShort i, j;
GXV_NAME_ENTER( "trackTable" );
@@ -108,9 +108,11 @@
GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFFU;
GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000;
+ GXV_LIMIT_CHECK( nTracks * ( 4 + 2 + 2 ) );
+
for ( i = 0; i < nTracks; i ++ )
{
- GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ p = table + i * ( 4 + 2 + 2 );
track = FT_NEXT_LONG( p );
nameIndex = FT_NEXT_USHORT( p );
offset = FT_NEXT_USHORT( p );
@@ -121,6 +123,15 @@
GXV_TRAK_DATA( trackValueOffset_max ) = offset;
gxv_sfntName_validate( nameIndex, 256, 32767, valid );
+
+ for ( j = i; j < nTracks; j ++ )
+ {
+ p = table + j * ( 4 + 2 + 2 );
+ t = FT_NEXT_LONG( p );
+ if ( t == track )
+ GXV_TRACE(( "duplicated entries found for track value 0x%x\n",
+ track ));
+ }
}
valid->subtable_length = p - table;
@@ -198,7 +209,6 @@
{
FT_Bytes p = table;
FT_Bytes limit = 0;
- FT_Offset table_size;
GXV_ValidatorRec validrec;
GXV_Validator valid = &validrec;
@@ -220,7 +230,6 @@
valid->face = face;
limit = valid->root->limit;
- table_size = limit - table;
FT_TRACE3(( "validating `trak' table\n" ));
GXV_INIT;