shithub: freetype+ttf2subf

Download patch

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.

git/fs: mount .git/fs: mount/attach disallowed
--- 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 )
     {