ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

gxvcommn.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  gxvcommn.c                                                             */
00004 /*                                                                         */
00005 /*    TrueTypeGX/AAT common tables validation (body).                      */
00006 /*                                                                         */
00007 /*  Copyright 2004, 2005, 2009, 2010                                       */
00008 /*  by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 /***************************************************************************/
00020 /*                                                                         */
00021 /* gxvalid is derived from both gxlayout module and otvalid module.        */
00022 /* Development of gxlayout is supported by the Information-technology      */
00023 /* Promotion Agency(IPA), Japan.                                           */
00024 /*                                                                         */
00025 /***************************************************************************/
00026 
00027 
00028 #include "gxvcommn.h"
00029 
00030 
00031   /*************************************************************************/
00032   /*                                                                       */
00033   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00034   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00035   /* messages during execution.                                            */
00036   /*                                                                       */
00037 #undef  FT_COMPONENT
00038 #define FT_COMPONENT  trace_gxvcommon
00039 
00040 
00041   /*************************************************************************/
00042   /*************************************************************************/
00043   /*****                                                               *****/
00044   /*****                       16bit offset sorter                     *****/
00045   /*****                                                               *****/
00046   /*************************************************************************/
00047   /*************************************************************************/
00048 
00049   static int
00050   gxv_compare_ushort_offset( FT_UShort*  a,
00051                              FT_UShort*  b )
00052   {
00053     if ( *a < *b )
00054       return -1;
00055     else if ( *a > *b )
00056       return 1;
00057     else
00058       return 0;
00059   }
00060 
00061 
00062   FT_LOCAL_DEF( void )
00063   gxv_set_length_by_ushort_offset( FT_UShort*     offset,
00064                                    FT_UShort**    length,
00065                                    FT_UShort*     buff,
00066                                    FT_UInt        nmemb,
00067                                    FT_UShort      limit,
00068                                    GXV_Validator  valid )
00069   {
00070     FT_UInt  i;
00071 
00072 
00073     for ( i = 0; i < nmemb; i++ )
00074       *(length[i]) = 0;
00075 
00076     for ( i = 0; i < nmemb; i++ )
00077       buff[i] = offset[i];
00078     buff[nmemb] = limit;
00079 
00080     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
00081               ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
00082 
00083     if ( buff[nmemb] > limit )
00084       FT_INVALID_OFFSET;
00085 
00086     for ( i = 0; i < nmemb; i++ )
00087     {
00088       FT_UInt  j;
00089 
00090 
00091       for ( j = 0; j < nmemb; j++ )
00092         if ( buff[j] == offset[i] )
00093           break;
00094 
00095       if ( j == nmemb )
00096         FT_INVALID_OFFSET;
00097 
00098       *(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
00099 
00100       if ( 0 != offset[i] && 0 == *(length[i]) )
00101         FT_INVALID_OFFSET;
00102     }
00103   }
00104 
00105 
00106   /*************************************************************************/
00107   /*************************************************************************/
00108   /*****                                                               *****/
00109   /*****                       32bit offset sorter                     *****/
00110   /*****                                                               *****/
00111   /*************************************************************************/
00112   /*************************************************************************/
00113 
00114   static int
00115   gxv_compare_ulong_offset( FT_ULong*  a,
00116                             FT_ULong*  b )
00117   {
00118     if ( *a < *b )
00119       return -1;
00120     else if ( *a > *b )
00121       return 1;
00122     else
00123       return 0;
00124   }
00125 
00126 
00127   FT_LOCAL_DEF( void )
00128   gxv_set_length_by_ulong_offset( FT_ULong*      offset,
00129                                   FT_ULong**     length,
00130                                   FT_ULong*      buff,
00131                                   FT_UInt        nmemb,
00132                                   FT_ULong       limit,
00133                                   GXV_Validator  valid)
00134   {
00135     FT_UInt  i;
00136 
00137 
00138     for ( i = 0; i < nmemb; i++ )
00139       *(length[i]) = 0;
00140 
00141     for ( i = 0; i < nmemb; i++ )
00142       buff[i] = offset[i];
00143     buff[nmemb] = limit;
00144 
00145     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
00146               ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
00147 
00148     if ( buff[nmemb] > limit )
00149       FT_INVALID_OFFSET;
00150 
00151     for ( i = 0; i < nmemb; i++ )
00152     {
00153       FT_UInt  j;
00154 
00155 
00156       for ( j = 0; j < nmemb; j++ )
00157         if ( buff[j] == offset[i] )
00158           break;
00159 
00160       if ( j == nmemb )
00161         FT_INVALID_OFFSET;
00162 
00163       *(length[i]) = buff[j + 1] - buff[j];
00164 
00165       if ( 0 != offset[i] && 0 == *(length[i]) )
00166         FT_INVALID_OFFSET;
00167     }
00168   }
00169 
00170 
00171   /*************************************************************************/
00172   /*************************************************************************/
00173   /*****                                                               *****/
00174   /*****               scan value array and get min & max              *****/
00175   /*****                                                               *****/
00176   /*************************************************************************/
00177   /*************************************************************************/
00178 
00179 
00180   FT_LOCAL_DEF( void )
00181   gxv_array_getlimits_byte( FT_Bytes       table,
00182                             FT_Bytes       limit,
00183                             FT_Byte*       min,
00184                             FT_Byte*       max,
00185                             GXV_Validator  valid )
00186   {
00187     FT_Bytes  p = table;
00188 
00189 
00190     *min = 0xFF;
00191     *max = 0x00;
00192 
00193     while ( p < limit )
00194     {
00195       FT_Byte  val;
00196 
00197 
00198       GXV_LIMIT_CHECK( 1 );
00199       val = FT_NEXT_BYTE( p );
00200 
00201       *min = (FT_Byte)FT_MIN( *min, val );
00202       *max = (FT_Byte)FT_MAX( *max, val );
00203     }
00204 
00205     valid->subtable_length = p - table;
00206   }
00207 
00208 
00209   FT_LOCAL_DEF( void )
00210   gxv_array_getlimits_ushort( FT_Bytes       table,
00211                               FT_Bytes       limit,
00212                               FT_UShort*     min,
00213                               FT_UShort*     max,
00214                               GXV_Validator  valid )
00215   {
00216     FT_Bytes  p = table;
00217 
00218 
00219     *min = 0xFFFFU;
00220     *max = 0x0000;
00221 
00222     while ( p < limit )
00223     {
00224       FT_UShort  val;
00225 
00226 
00227       GXV_LIMIT_CHECK( 2 );
00228       val = FT_NEXT_USHORT( p );
00229 
00230       *min = (FT_Byte)FT_MIN( *min, val );
00231       *max = (FT_Byte)FT_MAX( *max, val );
00232     }
00233 
00234     valid->subtable_length = p - table;
00235   }
00236 
00237 
00238   /*************************************************************************/
00239   /*************************************************************************/
00240   /*****                                                               *****/
00241   /*****                       BINSEARCHHEADER                         *****/
00242   /*****                                                               *****/
00243   /*************************************************************************/
00244   /*************************************************************************/
00245 
00246   typedef struct  GXV_BinSrchHeader_
00247   {
00248     FT_UShort  unitSize;
00249     FT_UShort  nUnits;
00250     FT_UShort  searchRange;
00251     FT_UShort  entrySelector;
00252     FT_UShort  rangeShift;
00253 
00254   } GXV_BinSrchHeader;
00255 
00256 
00257   static void
00258   gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader*  binSrchHeader,
00259                                        GXV_Validator       valid )
00260   {
00261     FT_UShort  searchRange;
00262     FT_UShort  entrySelector;
00263     FT_UShort  rangeShift;
00264 
00265 
00266     if ( binSrchHeader->unitSize == 0 )
00267       FT_INVALID_DATA;
00268 
00269     if ( binSrchHeader->nUnits == 0 )
00270     {
00271       if ( binSrchHeader->searchRange   == 0 &&
00272            binSrchHeader->entrySelector == 0 &&
00273            binSrchHeader->rangeShift    == 0 )
00274         return;
00275       else
00276         FT_INVALID_DATA;
00277     }
00278 
00279     for ( searchRange = 1, entrySelector = 1;
00280           ( searchRange * 2 ) <= binSrchHeader->nUnits &&
00281             searchRange < 0x8000U;
00282           searchRange *= 2, entrySelector++ )
00283       ;
00284 
00285     entrySelector--;
00286     searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
00287     rangeShift  = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
00288                                - searchRange );
00289 
00290     if ( searchRange   != binSrchHeader->searchRange   ||
00291          entrySelector != binSrchHeader->entrySelector ||
00292          rangeShift    != binSrchHeader->rangeShift    )
00293     {
00294       GXV_TRACE(( "Inconsistency found in BinSrchHeader\n" ));
00295       GXV_TRACE(( "originally: unitSize=%d, nUnits=%d, "
00296                   "searchRange=%d, entrySelector=%d, "
00297                   "rangeShift=%d\n",
00298                   binSrchHeader->unitSize, binSrchHeader->nUnits,
00299                   binSrchHeader->searchRange, binSrchHeader->entrySelector,
00300                   binSrchHeader->rangeShift ));
00301       GXV_TRACE(( "calculated: unitSize=%d, nUnits=%d, "
00302                   "searchRange=%d, entrySelector=%d, "
00303                   "rangeShift=%d\n",
00304                   binSrchHeader->unitSize, binSrchHeader->nUnits,
00305                   searchRange, entrySelector, rangeShift ));
00306 
00307       if ( valid->root->level >= FT_VALIDATE_PARANOID )
00308         FT_INVALID_DATA;
00309     }
00310   }
00311 
00312 
00313   /*
00314    * parser & validator of BinSrchHeader
00315    * which is used in LookupTable format 2, 4, 6.
00316    *
00317    * Essential parameters (unitSize, nUnits) are returned by
00318    * given pointer, others (searchRange, entrySelector, rangeShift)
00319    * can be calculated by essential parameters, so they are just
00320    * validated and discarded.
00321    *
00322    * However, wrong values in searchRange, entrySelector, rangeShift
00323    * won't cause fatal errors, because these parameters might be
00324    * only used in old m68k font driver in MacOS.
00325    *   -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
00326    */
00327 
00328   FT_LOCAL_DEF( void )
00329   gxv_BinSrchHeader_validate( FT_Bytes       table,
00330                               FT_Bytes       limit,
00331                               FT_UShort*     unitSize_p,
00332                               FT_UShort*     nUnits_p,
00333                               GXV_Validator  valid )
00334   {
00335     FT_Bytes           p = table;
00336     GXV_BinSrchHeader  binSrchHeader;
00337 
00338 
00339     GXV_NAME_ENTER( "BinSrchHeader validate" );
00340 
00341     if ( *unitSize_p == 0 )
00342     {
00343       GXV_LIMIT_CHECK( 2 );
00344       binSrchHeader.unitSize =  FT_NEXT_USHORT( p );
00345     }
00346     else
00347       binSrchHeader.unitSize = *unitSize_p;
00348 
00349     if ( *nUnits_p == 0 )
00350     {
00351       GXV_LIMIT_CHECK( 2 );
00352       binSrchHeader.nUnits = FT_NEXT_USHORT( p );
00353     }
00354     else
00355       binSrchHeader.nUnits = *nUnits_p;
00356 
00357     GXV_LIMIT_CHECK( 2 + 2 + 2 );
00358     binSrchHeader.searchRange   = FT_NEXT_USHORT( p );
00359     binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
00360     binSrchHeader.rangeShift    = FT_NEXT_USHORT( p );
00361     GXV_TRACE(( "nUnits %d\n", binSrchHeader.nUnits ));
00362 
00363     gxv_BinSrchHeader_check_consistency( &binSrchHeader, valid );
00364 
00365     if ( *unitSize_p == 0 )
00366       *unitSize_p = binSrchHeader.unitSize;
00367 
00368     if ( *nUnits_p == 0 )
00369       *nUnits_p = binSrchHeader.nUnits;
00370 
00371     valid->subtable_length = p - table;
00372     GXV_EXIT;
00373   }
00374 
00375 
00376   /*************************************************************************/
00377   /*************************************************************************/
00378   /*****                                                               *****/
00379   /*****                         LOOKUP TABLE                          *****/
00380   /*****                                                               *****/
00381   /*************************************************************************/
00382   /*************************************************************************/
00383 
00384 #define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC )                   \
00385           ( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
00386 
00387   static GXV_LookupValueDesc
00388   gxv_lookup_value_load( FT_Bytes  p,
00389                          int       signspec )
00390   {
00391     GXV_LookupValueDesc  v;
00392 
00393 
00394     if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
00395       v.u = FT_NEXT_USHORT( p );
00396     else
00397       v.s = FT_NEXT_SHORT( p );
00398 
00399     return v;
00400   }
00401 
00402 
00403 #define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
00404           FT_BEGIN_STMNT                                               \
00405             if ( UNITSIZE != CORRECTSIZE )                             \
00406             {                                                          \
00407               FT_ERROR(( "unitSize=%d differs from"                    \
00408                          " expected unitSize=%d"                       \
00409                          " in LookupTable %s\n",                       \
00410                           UNITSIZE, CORRECTSIZE, FORMAT ));            \
00411               if ( UNITSIZE != 0 && NUNITS != 0 )                      \
00412               {                                                        \
00413                 FT_ERROR(( " cannot validate anymore\n" ));            \
00414                 FT_INVALID_FORMAT;                                     \
00415               }                                                        \
00416               else                                                     \
00417                 FT_ERROR(( " forcibly continues\n" ));                 \
00418             }                                                          \
00419           FT_END_STMNT
00420 
00421 
00422   /* ================= Simple Array Format 0 Lookup Table ================ */
00423   static void
00424   gxv_LookupTable_fmt0_validate( FT_Bytes       table,
00425                                  FT_Bytes       limit,
00426                                  GXV_Validator  valid )
00427   {
00428     FT_Bytes   p = table;
00429     FT_UShort  i;
00430 
00431     GXV_LookupValueDesc  value;
00432 
00433 
00434     GXV_NAME_ENTER( "LookupTable format 0" );
00435 
00436     GXV_LIMIT_CHECK( 2 * valid->face->num_glyphs );
00437 
00438     for ( i = 0; i < valid->face->num_glyphs; i++ )
00439     {
00440       GXV_LIMIT_CHECK( 2 );
00441       if ( p + 2 >= limit )     /* some fonts have too-short fmt0 array */
00442       {
00443         GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
00444                     i, valid->face->num_glyphs ));
00445         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00446           FT_INVALID_GLYPH_ID;
00447         break;
00448       }
00449 
00450       value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
00451       valid->lookupval_func( i, &value, valid );
00452     }
00453 
00454     valid->subtable_length = p - table;
00455     GXV_EXIT;
00456   }
00457 
00458 
00459   /* ================= Segment Single Format 2 Loolup Table ============== */
00460   /*
00461    * Apple spec says:
00462    *
00463    *   To guarantee that a binary search terminates, you must include one or
00464    *   more special `end of search table' values at the end of the data to
00465    *   be searched.  The number of termination values that need to be
00466    *   included is table-specific.  The value that indicates binary search
00467    *   termination is 0xFFFF.
00468    *
00469    * The problem is that nUnits does not include this end-marker.  It's
00470    * quite difficult to discriminate whether the following 0xFFFF comes from
00471    * the end-marker or some next data.
00472    *
00473    *   -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
00474    */
00475   static void
00476   gxv_LookupTable_fmt2_skip_endmarkers( FT_Bytes       table,
00477                                         FT_UShort      unitSize,
00478                                         GXV_Validator  valid )
00479   {
00480     FT_Bytes  p = table;
00481 
00482 
00483     while ( ( p + 4 ) < valid->root->limit )
00484     {
00485       if ( p[0] != 0xFF || p[1] != 0xFF || /* lastGlyph */
00486            p[2] != 0xFF || p[3] != 0xFF )  /* firstGlyph */
00487         break;
00488       p += unitSize;
00489     }
00490 
00491     valid->subtable_length = p - table;
00492   }
00493 
00494 
00495   static void
00496   gxv_LookupTable_fmt2_validate( FT_Bytes       table,
00497                                  FT_Bytes       limit,
00498                                  GXV_Validator  valid )
00499   {
00500     FT_Bytes             p = table;
00501     FT_UShort            gid;
00502 
00503     FT_UShort            unitSize;
00504     FT_UShort            nUnits;
00505     FT_UShort            unit;
00506     FT_UShort            lastGlyph;
00507     FT_UShort            firstGlyph;
00508     GXV_LookupValueDesc  value;
00509 
00510 
00511     GXV_NAME_ENTER( "LookupTable format 2" );
00512 
00513     unitSize = nUnits = 0;
00514     gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
00515     p += valid->subtable_length;
00516 
00517     GXV_UNITSIZE_VALIDATE( "format2", unitSize, nUnits, 6 );
00518 
00519     for ( unit = 0, gid = 0; unit < nUnits; unit++ )
00520     {
00521       GXV_LIMIT_CHECK( 2 + 2 + 2 );
00522       lastGlyph  = FT_NEXT_USHORT( p );
00523       firstGlyph = FT_NEXT_USHORT( p );
00524       value      = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
00525 
00526       gxv_glyphid_validate( firstGlyph, valid );
00527       gxv_glyphid_validate( lastGlyph, valid );
00528 
00529       if ( lastGlyph < gid )
00530       {
00531         GXV_TRACE(( "reverse ordered segment specification:"
00532                     " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
00533                     unit, lastGlyph, unit - 1 , gid ));
00534         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00535           FT_INVALID_GLYPH_ID;
00536       }
00537 
00538       if ( lastGlyph < firstGlyph )
00539       {
00540         GXV_TRACE(( "reverse ordered range specification at unit %d:",
00541                     " lastGlyph %d < firstGlyph %d ",
00542                     unit, lastGlyph, firstGlyph ));
00543         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00544           FT_INVALID_GLYPH_ID;
00545 
00546         if ( valid->root->level == FT_VALIDATE_TIGHT )
00547           continue;     /* ftxvalidator silently skips such an entry */
00548 
00549         FT_TRACE4(( "continuing with exchanged values\n" ));
00550         gid        = firstGlyph;
00551         firstGlyph = lastGlyph;
00552         lastGlyph  = gid;
00553       }
00554 
00555       for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
00556         valid->lookupval_func( gid, &value, valid );
00557     }
00558 
00559     gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
00560     p += valid->subtable_length;
00561 
00562     valid->subtable_length = p - table;
00563     GXV_EXIT;
00564   }
00565 
00566 
00567   /* ================= Segment Array Format 4 Lookup Table =============== */
00568   static void
00569   gxv_LookupTable_fmt4_validate( FT_Bytes       table,
00570                                  FT_Bytes       limit,
00571                                  GXV_Validator  valid )
00572   {
00573     FT_Bytes             p = table;
00574     FT_UShort            unit;
00575     FT_UShort            gid;
00576 
00577     FT_UShort            unitSize;
00578     FT_UShort            nUnits;
00579     FT_UShort            lastGlyph;
00580     FT_UShort            firstGlyph;
00581     GXV_LookupValueDesc  base_value;
00582     GXV_LookupValueDesc  value;
00583 
00584 
00585     GXV_NAME_ENTER( "LookupTable format 4" );
00586 
00587     unitSize = nUnits = 0;
00588     gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
00589     p += valid->subtable_length;
00590 
00591     GXV_UNITSIZE_VALIDATE( "format4", unitSize, nUnits, 6 );
00592 
00593     for ( unit = 0, gid = 0; unit < nUnits; unit++ )
00594     {
00595       GXV_LIMIT_CHECK( 2 + 2 );
00596       lastGlyph  = FT_NEXT_USHORT( p );
00597       firstGlyph = FT_NEXT_USHORT( p );
00598 
00599       gxv_glyphid_validate( firstGlyph, valid );
00600       gxv_glyphid_validate( lastGlyph, valid );
00601 
00602       if ( lastGlyph < gid )
00603       {
00604         GXV_TRACE(( "reverse ordered segment specification:"
00605                     " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
00606                     unit, lastGlyph, unit - 1 , gid ));
00607         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00608           FT_INVALID_GLYPH_ID;
00609       }
00610 
00611       if ( lastGlyph < firstGlyph )
00612       {
00613         GXV_TRACE(( "reverse ordered range specification at unit %d:",
00614                     " lastGlyph %d < firstGlyph %d ",
00615                     unit, lastGlyph, firstGlyph ));
00616         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00617           FT_INVALID_GLYPH_ID;
00618 
00619         if ( valid->root->level == FT_VALIDATE_TIGHT )
00620           continue; /* ftxvalidator silently skips such an entry */
00621 
00622         FT_TRACE4(( "continuing with exchanged values\n" ));
00623         gid        = firstGlyph;
00624         firstGlyph = lastGlyph;
00625         lastGlyph  = gid;
00626       }
00627 
00628       GXV_LIMIT_CHECK( 2 );
00629       base_value = GXV_LOOKUP_VALUE_LOAD( p, GXV_LOOKUPVALUE_UNSIGNED );
00630 
00631       for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
00632       {
00633         value = valid->lookupfmt4_trans( (FT_UShort)( gid - firstGlyph ),
00634                                          &base_value,
00635                                          limit,
00636                                          valid );
00637 
00638         valid->lookupval_func( gid, &value, valid );
00639       }
00640     }
00641 
00642     gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
00643     p += valid->subtable_length;
00644 
00645     valid->subtable_length = p - table;
00646     GXV_EXIT;
00647   }
00648 
00649 
00650   /* ================= Segment Table Format 6 Lookup Table =============== */
00651   static void
00652   gxv_LookupTable_fmt6_skip_endmarkers( FT_Bytes       table,
00653                                         FT_UShort      unitSize,
00654                                         GXV_Validator  valid )
00655   {
00656     FT_Bytes  p = table;
00657 
00658 
00659     while ( p < valid->root->limit )
00660     {
00661       if ( p[0] != 0xFF || p[1] != 0xFF )
00662         break;
00663       p += unitSize;
00664     }
00665 
00666     valid->subtable_length = p - table;
00667   }
00668 
00669 
00670   static void
00671   gxv_LookupTable_fmt6_validate( FT_Bytes       table,
00672                                  FT_Bytes       limit,
00673                                  GXV_Validator  valid )
00674   {
00675     FT_Bytes             p = table;
00676     FT_UShort            unit;
00677     FT_UShort            prev_glyph;
00678 
00679     FT_UShort            unitSize;
00680     FT_UShort            nUnits;
00681     FT_UShort            glyph;
00682     GXV_LookupValueDesc  value;
00683 
00684 
00685     GXV_NAME_ENTER( "LookupTable format 6" );
00686 
00687     unitSize = nUnits = 0;
00688     gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
00689     p += valid->subtable_length;
00690 
00691     GXV_UNITSIZE_VALIDATE( "format6", unitSize, nUnits, 4 );
00692 
00693     for ( unit = 0, prev_glyph = 0; unit < nUnits; unit++ )
00694     {
00695       GXV_LIMIT_CHECK( 2 + 2 );
00696       glyph = FT_NEXT_USHORT( p );
00697       value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
00698 
00699       if ( gxv_glyphid_validate( glyph, valid ) )
00700         GXV_TRACE(( " endmarker found within defined range"
00701                     " (entry %d < nUnits=%d)\n",
00702                     unit, nUnits ));
00703 
00704       if ( prev_glyph > glyph )
00705       {
00706         GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
00707                     glyph, prev_glyph ));
00708         if ( valid->root->level >= FT_VALIDATE_PARANOID )
00709           FT_INVALID_GLYPH_ID;
00710       }
00711       prev_glyph = glyph;
00712 
00713       valid->lookupval_func( glyph, &value, valid );
00714     }
00715 
00716     gxv_LookupTable_fmt6_skip_endmarkers( p, unitSize, valid );
00717     p += valid->subtable_length;
00718 
00719     valid->subtable_length = p - table;
00720     GXV_EXIT;
00721   }
00722 
00723 
00724   /* ================= Trimmed Array Format 8 Lookup Table =============== */
00725   static void
00726   gxv_LookupTable_fmt8_validate( FT_Bytes       table,
00727                                  FT_Bytes       limit,
00728                                  GXV_Validator  valid )
00729   {
00730     FT_Bytes              p = table;
00731     FT_UShort             i;
00732 
00733     GXV_LookupValueDesc   value;
00734     FT_UShort             firstGlyph;
00735     FT_UShort             glyphCount;
00736 
00737 
00738     GXV_NAME_ENTER( "LookupTable format 8" );
00739 
00740     /* firstGlyph + glyphCount */
00741     GXV_LIMIT_CHECK( 2 + 2 );
00742     firstGlyph = FT_NEXT_USHORT( p );
00743     glyphCount = FT_NEXT_USHORT( p );
00744 
00745     gxv_glyphid_validate( firstGlyph, valid );
00746     gxv_glyphid_validate( (FT_UShort)( firstGlyph + glyphCount ), valid );
00747 
00748     /* valueArray */
00749     for ( i = 0; i < glyphCount; i++ )
00750     {
00751       GXV_LIMIT_CHECK( 2 );
00752       value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
00753       valid->lookupval_func( (FT_UShort)( firstGlyph + i ), &value, valid );
00754     }
00755 
00756     valid->subtable_length = p - table;
00757     GXV_EXIT;
00758   }
00759 
00760 
00761   FT_LOCAL_DEF( void )
00762   gxv_LookupTable_validate( FT_Bytes       table,
00763                             FT_Bytes       limit,
00764                             GXV_Validator  valid )
00765   {
00766     FT_Bytes   p = table;
00767     FT_UShort  format;
00768 
00769     GXV_Validate_Func  fmt_funcs_table[] =
00770     {
00771       gxv_LookupTable_fmt0_validate, /* 0 */
00772       NULL,                          /* 1 */
00773       gxv_LookupTable_fmt2_validate, /* 2 */
00774       NULL,                          /* 3 */
00775       gxv_LookupTable_fmt4_validate, /* 4 */
00776       NULL,                          /* 5 */
00777       gxv_LookupTable_fmt6_validate, /* 6 */
00778       NULL,                          /* 7 */
00779       gxv_LookupTable_fmt8_validate, /* 8 */
00780     };
00781 
00782     GXV_Validate_Func  func;
00783 
00784 
00785     GXV_NAME_ENTER( "LookupTable" );
00786 
00787     /* lookuptbl_head may be used in fmt4 transit function. */
00788     valid->lookuptbl_head = table;
00789 
00790     /* format */
00791     GXV_LIMIT_CHECK( 2 );
00792     format = FT_NEXT_USHORT( p );
00793     GXV_TRACE(( " (format %d)\n", format ));
00794 
00795     if ( format > 8 )
00796       FT_INVALID_FORMAT;
00797 
00798     func = fmt_funcs_table[format];
00799     if ( func == NULL )
00800       FT_INVALID_FORMAT;
00801 
00802     func( p, limit, valid );
00803     p += valid->subtable_length;
00804 
00805     valid->subtable_length = p - table;
00806 
00807     GXV_EXIT;
00808   }
00809 
00810 
00811   /*************************************************************************/
00812   /*************************************************************************/
00813   /*****                                                               *****/
00814   /*****                          Glyph ID                             *****/
00815   /*****                                                               *****/
00816   /*************************************************************************/
00817   /*************************************************************************/
00818 
00819   FT_LOCAL_DEF( FT_Int )
00820   gxv_glyphid_validate( FT_UShort      gid,
00821                         GXV_Validator  valid )
00822   {
00823     FT_Face  face;
00824 
00825 
00826     if ( gid == 0xFFFFU )
00827     {
00828       GXV_EXIT;
00829       return 1;
00830     }
00831 
00832     face = valid->face;
00833     if ( face->num_glyphs < gid )
00834     {
00835       GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
00836                   face->num_glyphs, gid ));
00837       if ( valid->root->level >= FT_VALIDATE_PARANOID )
00838         FT_INVALID_GLYPH_ID;
00839     }
00840 
00841     return 0;
00842   }
00843 
00844 
00845   /*************************************************************************/
00846   /*************************************************************************/
00847   /*****                                                               *****/
00848   /*****                        CONTROL POINT                          *****/
00849   /*****                                                               *****/
00850   /*************************************************************************/
00851   /*************************************************************************/
00852 
00853   FT_LOCAL_DEF( void )
00854   gxv_ctlPoint_validate( FT_UShort      gid,
00855                          FT_Short       ctl_point,
00856                          GXV_Validator  valid )
00857   {
00858     FT_Face       face;
00859     FT_Error      error;
00860 
00861     FT_GlyphSlot  glyph;
00862     FT_Outline    outline;
00863     short         n_points;
00864 
00865 
00866     face = valid->face;
00867 
00868     error = FT_Load_Glyph( face,
00869                            gid,
00870                            FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM );
00871     if ( error )
00872       FT_INVALID_GLYPH_ID;
00873 
00874     glyph    = face->glyph;
00875     outline  = glyph->outline;
00876     n_points = outline.n_points;
00877 
00878 
00879     if ( !( ctl_point < n_points ) )
00880       FT_INVALID_DATA;
00881   }
00882 
00883 
00884   /*************************************************************************/
00885   /*************************************************************************/
00886   /*****                                                               *****/
00887   /*****                          SFNT NAME                            *****/
00888   /*****                                                               *****/
00889   /*************************************************************************/
00890   /*************************************************************************/
00891 
00892   FT_LOCAL_DEF( void )
00893   gxv_sfntName_validate( FT_UShort      name_index,
00894                          FT_UShort      min_index,
00895                          FT_UShort      max_index,
00896                          GXV_Validator  valid )
00897   {
00898     FT_SfntName  name;
00899     FT_UInt      i;
00900     FT_UInt      nnames;
00901 
00902 
00903     GXV_NAME_ENTER( "sfntName" );
00904 
00905     if ( name_index < min_index || max_index < name_index )
00906       FT_INVALID_FORMAT;
00907 
00908     nnames = FT_Get_Sfnt_Name_Count( valid->face );
00909     for ( i = 0; i < nnames; i++ )
00910     {
00911       if ( FT_Get_Sfnt_Name( valid->face, i, &name ) != GXV_Err_Ok )
00912         continue ;
00913 
00914       if ( name.name_id == name_index )
00915         goto Out;
00916     }
00917 
00918     GXV_TRACE(( "  nameIndex = %d (UNTITLED)\n", name_index ));
00919     FT_INVALID_DATA;
00920     goto Exit;  /* make compiler happy */
00921 
00922   Out:
00923     FT_TRACE1(( "  nameIndex = %d (", name_index ));
00924     GXV_TRACE_HEXDUMP_SFNTNAME( name );
00925     FT_TRACE1(( ")\n" ));
00926 
00927   Exit:
00928     GXV_EXIT;
00929   }
00930 
00931 
00932   /*************************************************************************/
00933   /*************************************************************************/
00934   /*****                                                               *****/
00935   /*****                          STATE TABLE                          *****/
00936   /*****                                                               *****/
00937   /*************************************************************************/
00938   /*************************************************************************/
00939 
00940   /* -------------------------- Class Table --------------------------- */
00941 
00942   /*
00943    * highestClass specifies how many classes are defined in this
00944    * Class Subtable.  Apple spec does not mention whether undefined
00945    * holes in the class (e.g.: 0-3 are predefined, 4 is unused, 5 is used)
00946    * are permitted.  At present, holes in a defined class are not checked.
00947    *   -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
00948    */
00949 
00950   static void
00951   gxv_ClassTable_validate( FT_Bytes       table,
00952                            FT_UShort*     length_p,
00953                            FT_UShort      stateSize,
00954                            FT_Byte*       maxClassID_p,
00955                            GXV_Validator  valid )
00956   {
00957     FT_Bytes   p     = table;
00958     FT_Bytes   limit = table + *length_p;
00959     FT_UShort  firstGlyph;
00960     FT_UShort  nGlyphs;
00961 
00962 
00963     GXV_NAME_ENTER( "ClassTable" );
00964 
00965     *maxClassID_p = 3;  /* Classes 0, 2, and 3 are predefined */
00966 
00967     GXV_LIMIT_CHECK( 2 + 2 );
00968     firstGlyph = FT_NEXT_USHORT( p );
00969     nGlyphs    = FT_NEXT_USHORT( p );
00970 
00971     GXV_TRACE(( " (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs ));
00972 
00973     if ( !nGlyphs )
00974       goto Out;
00975 
00976     gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), valid );
00977 
00978     {
00979       FT_Byte    nGlyphInClass[256];
00980       FT_Byte    classID;
00981       FT_UShort  i;
00982 
00983 
00984       ft_memset( nGlyphInClass, 0, 256 );
00985 
00986 
00987       for ( i = 0; i < nGlyphs; i++ )
00988       {
00989         GXV_LIMIT_CHECK( 1 );
00990         classID = FT_NEXT_BYTE( p );
00991         switch ( classID )
00992         {
00993           /* following classes should not appear in class array */
00994         case 0:             /* end of text */
00995         case 2:             /* out of bounds */
00996         case 3:             /* end of line */
00997           FT_INVALID_DATA;
00998           break;
00999 
01000         case 1:             /* out of bounds */
01001         default:            /* user-defined: 4 - ( stateSize - 1 ) */
01002           if ( classID >= stateSize )
01003             FT_INVALID_DATA;   /* assign glyph to undefined state */
01004 
01005           nGlyphInClass[classID]++;
01006           break;
01007         }
01008       }
01009       *length_p = (FT_UShort)( p - table );
01010 
01011       /* scan max ClassID in use */
01012       for ( i = 0; i < stateSize; i++ )
01013         if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) )
01014           *maxClassID_p = (FT_Byte)i;  /* XXX: Check Range? */
01015     }
01016 
01017   Out:
01018     GXV_TRACE(( "Declared stateSize=0x%02x, Used maxClassID=0x%02x\n",
01019                 stateSize, *maxClassID_p ));
01020     GXV_EXIT;
01021   }
01022 
01023 
01024   /* --------------------------- State Array ----------------------------- */
01025 
01026   static void
01027   gxv_StateArray_validate( FT_Bytes       table,
01028                            FT_UShort*     length_p,
01029                            FT_Byte        maxClassID,
01030                            FT_UShort      stateSize,
01031                            FT_Byte*       maxState_p,
01032                            FT_Byte*       maxEntry_p,
01033                            GXV_Validator  valid )
01034   {
01035     FT_Bytes  p = table;
01036     FT_Bytes  limit = table + *length_p;
01037     FT_Byte   clazz;
01038     FT_Byte   entry;
01039 
01040     FT_UNUSED( stateSize ); /* for the non-debugging case */
01041 
01042 
01043     GXV_NAME_ENTER( "StateArray" );
01044 
01045     GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n",
01046                 (int)(*length_p), stateSize, (int)(maxClassID) ));
01047 
01048     /*
01049      * 2 states are predefined and must be described in StateArray:
01050      * state 0 (start of text), 1 (start of line)
01051      */
01052     GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 );
01053 
01054     *maxState_p = 0;
01055     *maxEntry_p = 0;
01056 
01057     /* read if enough to read another state */
01058     while ( p + ( 1 + maxClassID ) <= limit )
01059     {
01060       (*maxState_p)++;
01061       for ( clazz = 0; clazz <= maxClassID; clazz++ )
01062       {
01063         entry = FT_NEXT_BYTE( p );
01064         *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry );
01065       }
01066     }
01067     GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
01068                 *maxState_p, *maxEntry_p ));
01069 
01070     *length_p = (FT_UShort)( p - table );
01071 
01072     GXV_EXIT;
01073   }
01074 
01075 
01076   /* --------------------------- Entry Table ----------------------------- */
01077 
01078   static void
01079   gxv_EntryTable_validate( FT_Bytes       table,
01080                            FT_UShort*     length_p,
01081                            FT_Byte        maxEntry,
01082                            FT_UShort      stateArray,
01083                            FT_UShort      stateArray_length,
01084                            FT_Byte        maxClassID,
01085                            FT_Bytes       statetable_table,
01086                            FT_Bytes       statetable_limit,
01087                            GXV_Validator  valid )
01088   {
01089     FT_Bytes  p     = table;
01090     FT_Bytes  limit = table + *length_p;
01091     FT_Byte   entry;
01092     FT_Byte   state;
01093     FT_Int    entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable );
01094 
01095     GXV_XStateTable_GlyphOffsetDesc  glyphOffset;
01096 
01097 
01098     GXV_NAME_ENTER( "EntryTable" );
01099 
01100     GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
01101 
01102     if ( ( maxEntry + 1 ) * entrySize > *length_p )
01103     {
01104       if ( valid->root->level >= FT_VALIDATE_PARANOID )
01105         FT_INVALID_TOO_SHORT;
01106 
01107       /* ftxvalidator and FontValidator both warn and continue */
01108       maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
01109       GXV_TRACE(( "too large maxEntry, shrinking to %d fit EntryTable length\n",
01110                   maxEntry ));
01111     }
01112 
01113     for ( entry = 0; entry <= maxEntry; entry++ )
01114     {
01115       FT_UShort  newState;
01116       FT_UShort  flags;
01117 
01118 
01119       GXV_LIMIT_CHECK( 2 + 2 );
01120       newState = FT_NEXT_USHORT( p );
01121       flags    = FT_NEXT_USHORT( p );
01122 
01123 
01124       if ( newState < stateArray                     ||
01125            stateArray + stateArray_length < newState )
01126       {
01127         GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
01128                     newState ));
01129         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01130           FT_INVALID_OFFSET;
01131         continue;
01132       }
01133 
01134       if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) )
01135       {
01136         GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
01137                     newState,  1 + maxClassID ));
01138         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01139           FT_INVALID_OFFSET;
01140         continue;
01141       }
01142 
01143       state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) );
01144 
01145       switch ( GXV_GLYPHOFFSET_FMT( statetable ) )
01146       {
01147       case GXV_GLYPHOFFSET_NONE:
01148         glyphOffset.uc = 0;  /* make compiler happy */
01149         break;
01150 
01151       case GXV_GLYPHOFFSET_UCHAR:
01152         glyphOffset.uc = FT_NEXT_BYTE( p );
01153         break;
01154 
01155       case GXV_GLYPHOFFSET_CHAR:
01156         glyphOffset.c = FT_NEXT_CHAR( p );
01157         break;
01158 
01159       case GXV_GLYPHOFFSET_USHORT:
01160         glyphOffset.u = FT_NEXT_USHORT( p );
01161         break;
01162 
01163       case GXV_GLYPHOFFSET_SHORT:
01164         glyphOffset.s = FT_NEXT_SHORT( p );
01165         break;
01166 
01167       case GXV_GLYPHOFFSET_ULONG:
01168         glyphOffset.ul = FT_NEXT_ULONG( p );
01169         break;
01170 
01171       case GXV_GLYPHOFFSET_LONG:
01172         glyphOffset.l = FT_NEXT_LONG( p );
01173         break;
01174 
01175       default:
01176         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01177           FT_INVALID_FORMAT;
01178         goto Exit;
01179       }
01180 
01181       if ( NULL != valid->statetable.entry_validate_func )
01182         valid->statetable.entry_validate_func( state,
01183                                                flags,
01184                                                &glyphOffset,
01185                                                statetable_table,
01186                                                statetable_limit,
01187                                                valid );
01188     }
01189 
01190   Exit:
01191     *length_p = (FT_UShort)( p - table );
01192 
01193     GXV_EXIT;
01194   }
01195 
01196 
01197   /* =========================== State Table ============================= */
01198 
01199   FT_LOCAL_DEF( void )
01200   gxv_StateTable_subtable_setup( FT_UShort      table_size,
01201                                  FT_UShort      classTable,
01202                                  FT_UShort      stateArray,
01203                                  FT_UShort      entryTable,
01204                                  FT_UShort*     classTable_length_p,
01205                                  FT_UShort*     stateArray_length_p,
01206                                  FT_UShort*     entryTable_length_p,
01207                                  GXV_Validator  valid )
01208   {
01209     FT_UShort   o[3];
01210     FT_UShort*  l[3];
01211     FT_UShort   buff[4];
01212 
01213 
01214     o[0] = classTable;
01215     o[1] = stateArray;
01216     o[2] = entryTable;
01217     l[0] = classTable_length_p;
01218     l[1] = stateArray_length_p;
01219     l[2] = entryTable_length_p;
01220 
01221     gxv_set_length_by_ushort_offset( o, l, buff, 3, table_size, valid );
01222   }
01223 
01224 
01225   FT_LOCAL_DEF( void )
01226   gxv_StateTable_validate( FT_Bytes       table,
01227                            FT_Bytes       limit,
01228                            GXV_Validator  valid )
01229   {
01230     FT_UShort   stateSize;
01231     FT_UShort   classTable;     /* offset to Class(Sub)Table */
01232     FT_UShort   stateArray;     /* offset to StateArray */
01233     FT_UShort   entryTable;     /* offset to EntryTable */
01234 
01235     FT_UShort   classTable_length;
01236     FT_UShort   stateArray_length;
01237     FT_UShort   entryTable_length;
01238     FT_Byte     maxClassID;
01239     FT_Byte     maxState;
01240     FT_Byte     maxEntry;
01241 
01242     GXV_StateTable_Subtable_Setup_Func  setup_func;
01243 
01244     FT_Bytes    p = table;
01245 
01246 
01247     GXV_NAME_ENTER( "StateTable" );
01248 
01249     GXV_TRACE(( "StateTable header\n" ));
01250 
01251     GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
01252     stateSize  = FT_NEXT_USHORT( p );
01253     classTable = FT_NEXT_USHORT( p );
01254     stateArray = FT_NEXT_USHORT( p );
01255     entryTable = FT_NEXT_USHORT( p );
01256 
01257     GXV_TRACE(( "stateSize=0x%04x\n", stateSize ));
01258     GXV_TRACE(( "offset to classTable=0x%04x\n", classTable ));
01259     GXV_TRACE(( "offset to stateArray=0x%04x\n", stateArray ));
01260     GXV_TRACE(( "offset to entryTable=0x%04x\n", entryTable ));
01261 
01262     if ( stateSize > 0xFF )
01263       FT_INVALID_DATA;
01264 
01265     if ( valid->statetable.optdata_load_func != NULL )
01266       valid->statetable.optdata_load_func( p, limit, valid );
01267 
01268     if ( valid->statetable.subtable_setup_func != NULL)
01269       setup_func = valid->statetable.subtable_setup_func;
01270     else
01271       setup_func = gxv_StateTable_subtable_setup;
01272 
01273     setup_func( (FT_UShort)( limit - table ),
01274                 classTable,
01275                 stateArray,
01276                 entryTable,
01277                 &classTable_length,
01278                 &stateArray_length,
01279                 &entryTable_length,
01280                 valid );
01281 
01282     GXV_TRACE(( "StateTable Subtables\n" ));
01283 
01284     if ( classTable != 0 )
01285       gxv_ClassTable_validate( table + classTable,
01286                                &classTable_length,
01287                                stateSize,
01288                                &maxClassID,
01289                                valid );
01290     else
01291       maxClassID = (FT_Byte)( stateSize - 1 );
01292 
01293     if ( stateArray != 0 )
01294       gxv_StateArray_validate( table + stateArray,
01295                                &stateArray_length,
01296                                maxClassID,
01297                                stateSize,
01298                                &maxState,
01299                                &maxEntry,
01300                                valid );
01301     else
01302     {
01303       maxState = 1;     /* 0:start of text, 1:start of line are predefined */
01304       maxEntry = 0;
01305     }
01306 
01307     if ( maxEntry > 0 && entryTable == 0 )
01308       FT_INVALID_OFFSET;
01309 
01310     if ( entryTable != 0 )
01311       gxv_EntryTable_validate( table + entryTable,
01312                                &entryTable_length,
01313                                maxEntry,
01314                                stateArray,
01315                                stateArray_length,
01316                                maxClassID,
01317                                table,
01318                                limit,
01319                                valid );
01320 
01321     GXV_EXIT;
01322   }
01323 
01324 
01325   /* ================= eXtended State Table (for morx) =================== */
01326 
01327   FT_LOCAL_DEF( void )
01328   gxv_XStateTable_subtable_setup( FT_ULong       table_size,
01329                                   FT_ULong       classTable,
01330                                   FT_ULong       stateArray,
01331                                   FT_ULong       entryTable,
01332                                   FT_ULong*      classTable_length_p,
01333                                   FT_ULong*      stateArray_length_p,
01334                                   FT_ULong*      entryTable_length_p,
01335                                   GXV_Validator  valid )
01336   {
01337     FT_ULong   o[3];
01338     FT_ULong*  l[3];
01339     FT_ULong   buff[4];
01340 
01341 
01342     o[0] = classTable;
01343     o[1] = stateArray;
01344     o[2] = entryTable;
01345     l[0] = classTable_length_p;
01346     l[1] = stateArray_length_p;
01347     l[2] = entryTable_length_p;
01348 
01349     gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
01350   }
01351 
01352 
01353   static void
01354   gxv_XClassTable_lookupval_validate( FT_UShort            glyph,
01355                                       GXV_LookupValueCPtr  value_p,
01356                                       GXV_Validator        valid )
01357   {
01358     FT_UNUSED( glyph );
01359 
01360     if ( value_p->u >= valid->xstatetable.nClasses )
01361       FT_INVALID_DATA;
01362     if ( value_p->u > valid->xstatetable.maxClassID )
01363       valid->xstatetable.maxClassID = value_p->u;
01364   }
01365 
01366 
01367   /*
01368     +===============+ --------+
01369     | lookup header |         |
01370     +===============+         |
01371     | BinSrchHeader |         |
01372     +===============+         |
01373     | lastGlyph[0]  |         |
01374     +---------------+         |
01375     | firstGlyph[0] |         |    head of lookup table
01376     +---------------+         |             +
01377     | offset[0]     |    ->   |          offset            [byte]
01378     +===============+         |             +
01379     | lastGlyph[1]  |         | (glyphID - firstGlyph) * 2 [byte]
01380     +---------------+         |
01381     | firstGlyph[1] |         |
01382     +---------------+         |
01383     | offset[1]     |         |
01384     +===============+         |
01385                               |
01386      ....                     |
01387                               |
01388     16bit value array         |
01389     +===============+         |
01390     |     value     | <-------+
01391      ....
01392   */
01393   static GXV_LookupValueDesc
01394   gxv_XClassTable_lookupfmt4_transit( FT_UShort            relative_gindex,
01395                                       GXV_LookupValueCPtr  base_value_p,
01396                                       FT_Bytes             lookuptbl_limit,
01397                                       GXV_Validator        valid )
01398   {
01399     FT_Bytes             p;
01400     FT_Bytes             limit;
01401     FT_UShort            offset;
01402     GXV_LookupValueDesc  value;
01403 
01404     /* XXX: check range? */
01405     offset = (FT_UShort)( base_value_p->u +
01406                           relative_gindex * sizeof ( FT_UShort ) );
01407 
01408     p     = valid->lookuptbl_head + offset;
01409     limit = lookuptbl_limit;
01410 
01411     GXV_LIMIT_CHECK ( 2 );
01412     value.u = FT_NEXT_USHORT( p );
01413 
01414     return value;
01415   }
01416 
01417 
01418   static void
01419   gxv_XStateArray_validate( FT_Bytes       table,
01420                             FT_ULong*      length_p,
01421                             FT_UShort      maxClassID,
01422                             FT_ULong       stateSize,
01423                             FT_UShort*     maxState_p,
01424                             FT_UShort*     maxEntry_p,
01425                             GXV_Validator  valid )
01426   {
01427     FT_Bytes   p = table;
01428     FT_Bytes   limit = table + *length_p;
01429     FT_UShort  clazz;
01430     FT_UShort  entry;
01431 
01432     FT_UNUSED( stateSize ); /* for the non-debugging case */
01433 
01434 
01435     GXV_NAME_ENTER( "XStateArray" );
01436 
01437     GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
01438                 (int)(*length_p), stateSize, (int)(maxClassID) ));
01439 
01440     /*
01441      * 2 states are predefined and must be described:
01442      * state 0 (start of text), 1 (start of line)
01443      */
01444     GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 );
01445 
01446     *maxState_p = 0;
01447     *maxEntry_p = 0;
01448 
01449     /* read if enough to read another state */
01450     while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit )
01451     {
01452       (*maxState_p)++;
01453       for ( clazz = 0; clazz <= maxClassID; clazz++ )
01454       {
01455         entry = FT_NEXT_USHORT( p );
01456         *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry );
01457       }
01458     }
01459     GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
01460                 *maxState_p, *maxEntry_p ));
01461 
01462     *length_p = p - table;
01463 
01464     GXV_EXIT;
01465   }
01466 
01467 
01468   static void
01469   gxv_XEntryTable_validate( FT_Bytes       table,
01470                             FT_ULong*      length_p,
01471                             FT_UShort      maxEntry,
01472                             FT_ULong       stateArray_length,
01473                             FT_UShort      maxClassID,
01474                             FT_Bytes       xstatetable_table,
01475                             FT_Bytes       xstatetable_limit,
01476                             GXV_Validator  valid )
01477   {
01478     FT_Bytes   p = table;
01479     FT_Bytes   limit = table + *length_p;
01480     FT_UShort  entry;
01481     FT_UShort  state;
01482     FT_Int     entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable );
01483 
01484 
01485     GXV_NAME_ENTER( "XEntryTable" );
01486     GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
01487 
01488     if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
01489       FT_INVALID_TOO_SHORT;
01490 
01491     for (entry = 0; entry <= maxEntry ; entry++ )
01492     {
01493       FT_UShort                        newState_idx;
01494       FT_UShort                        flags;
01495       GXV_XStateTable_GlyphOffsetDesc  glyphOffset;
01496 
01497 
01498       GXV_LIMIT_CHECK( 2 + 2 );
01499       newState_idx = FT_NEXT_USHORT( p );
01500       flags        = FT_NEXT_USHORT( p );
01501 
01502       if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) )
01503       {
01504         GXV_TRACE(( "  newState index 0x%04x points out of stateArray\n",
01505                     newState_idx ));
01506         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01507           FT_INVALID_OFFSET;
01508       }
01509 
01510       state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
01511       if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
01512       {
01513         FT_TRACE4(( "-> new state = %d (supposed)\n"
01514                     "but newState index 0x%04x is not aligned to %d-classes\n",
01515                     state, newState_idx,  1 + maxClassID ));
01516         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01517           FT_INVALID_OFFSET;
01518       }
01519 
01520       switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
01521       {
01522       case GXV_GLYPHOFFSET_NONE:
01523         glyphOffset.uc = 0; /* make compiler happy */
01524         break;
01525 
01526       case GXV_GLYPHOFFSET_UCHAR:
01527         glyphOffset.uc = FT_NEXT_BYTE( p );
01528         break;
01529 
01530       case GXV_GLYPHOFFSET_CHAR:
01531         glyphOffset.c = FT_NEXT_CHAR( p );
01532         break;
01533 
01534       case GXV_GLYPHOFFSET_USHORT:
01535         glyphOffset.u = FT_NEXT_USHORT( p );
01536         break;
01537 
01538       case GXV_GLYPHOFFSET_SHORT:
01539         glyphOffset.s = FT_NEXT_SHORT( p );
01540         break;
01541 
01542       case GXV_GLYPHOFFSET_ULONG:
01543         glyphOffset.ul = FT_NEXT_ULONG( p );
01544         break;
01545 
01546       case GXV_GLYPHOFFSET_LONG:
01547         glyphOffset.l = FT_NEXT_LONG( p );
01548         break;
01549 
01550       default:
01551         if ( valid->root->level >= FT_VALIDATE_PARANOID )
01552           FT_INVALID_FORMAT;
01553         goto Exit;
01554       }
01555 
01556       if ( NULL != valid->xstatetable.entry_validate_func )
01557         valid->xstatetable.entry_validate_func( state,
01558                                                 flags,
01559                                                 &glyphOffset,
01560                                                 xstatetable_table,
01561                                                 xstatetable_limit,
01562                                                 valid );
01563     }
01564 
01565   Exit:
01566     *length_p = p - table;
01567 
01568     GXV_EXIT;
01569   }
01570 
01571 
01572   FT_LOCAL_DEF( void )
01573   gxv_XStateTable_validate( FT_Bytes       table,
01574                             FT_Bytes       limit,
01575                             GXV_Validator  valid )
01576   {
01577     /* StateHeader members */
01578     FT_ULong   classTable;      /* offset to Class(Sub)Table */
01579     FT_ULong   stateArray;      /* offset to StateArray */
01580     FT_ULong   entryTable;      /* offset to EntryTable */
01581 
01582     FT_ULong   classTable_length;
01583     FT_ULong   stateArray_length;
01584     FT_ULong   entryTable_length;
01585     FT_UShort  maxState;
01586     FT_UShort  maxEntry;
01587 
01588     GXV_XStateTable_Subtable_Setup_Func  setup_func;
01589 
01590     FT_Bytes   p = table;
01591 
01592 
01593     GXV_NAME_ENTER( "XStateTable" );
01594 
01595     GXV_TRACE(( "XStateTable header\n" ));
01596 
01597     GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
01598     valid->xstatetable.nClasses = FT_NEXT_ULONG( p );
01599     classTable = FT_NEXT_ULONG( p );
01600     stateArray = FT_NEXT_ULONG( p );
01601     entryTable = FT_NEXT_ULONG( p );
01602 
01603     GXV_TRACE(( "nClasses =0x%08x\n", valid->xstatetable.nClasses ));
01604     GXV_TRACE(( "offset to classTable=0x%08x\n", classTable ));
01605     GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray ));
01606     GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable ));
01607 
01608     if ( valid->xstatetable.nClasses > 0xFFFFU )
01609       FT_INVALID_DATA;
01610 
01611     GXV_TRACE(( "StateTable Subtables\n" ));
01612 
01613     if ( valid->xstatetable.optdata_load_func != NULL )
01614       valid->xstatetable.optdata_load_func( p, limit, valid );
01615 
01616     if ( valid->xstatetable.subtable_setup_func != NULL )
01617       setup_func = valid->xstatetable.subtable_setup_func;
01618     else
01619       setup_func = gxv_XStateTable_subtable_setup;
01620 
01621     setup_func( limit - table,
01622                 classTable,
01623                 stateArray,
01624                 entryTable,
01625                 &classTable_length,
01626                 &stateArray_length,
01627                 &entryTable_length,
01628                 valid );
01629 
01630     if ( classTable != 0 )
01631     {
01632       valid->xstatetable.maxClassID = 0;
01633       valid->lookupval_sign         = GXV_LOOKUPVALUE_UNSIGNED;
01634       valid->lookupval_func         = gxv_XClassTable_lookupval_validate;
01635       valid->lookupfmt4_trans       = gxv_XClassTable_lookupfmt4_transit;
01636       gxv_LookupTable_validate( table + classTable,
01637                                 table + classTable + classTable_length,
01638                                 valid );
01639       if ( valid->subtable_length < classTable_length )
01640         classTable_length = valid->subtable_length;
01641     }
01642     else
01643     {
01644       /* XXX: check range? */
01645       valid->xstatetable.maxClassID =
01646         (FT_UShort)( valid->xstatetable.nClasses - 1 );
01647     }
01648 
01649     if ( stateArray != 0 )
01650       gxv_XStateArray_validate( table + stateArray,
01651                                 &stateArray_length,
01652                                 valid->xstatetable.maxClassID,
01653                                 valid->xstatetable.nClasses,
01654                                 &maxState,
01655                                 &maxEntry,
01656                                 valid );
01657     else
01658     {
01659       maxState = 1; /* 0:start of text, 1:start of line are predefined */
01660       maxEntry = 0;
01661     }
01662 
01663     if ( maxEntry > 0 && entryTable == 0 )
01664       FT_INVALID_OFFSET;
01665 
01666     if ( entryTable != 0 )
01667       gxv_XEntryTable_validate( table + entryTable,
01668                                 &entryTable_length,
01669                                 maxEntry,
01670                                 stateArray_length,
01671                                 valid->xstatetable.maxClassID,
01672                                 table,
01673                                 limit,
01674                                 valid );
01675 
01676     GXV_EXIT;
01677   }
01678 
01679 
01680   /*************************************************************************/
01681   /*************************************************************************/
01682   /*****                                                               *****/
01683   /*****                        Table overlapping                      *****/
01684   /*****                                                               *****/
01685   /*************************************************************************/
01686   /*************************************************************************/
01687 
01688   static int
01689   gxv_compare_ranges( FT_Bytes  table1_start,
01690                       FT_ULong  table1_length,
01691                       FT_Bytes  table2_start,
01692                       FT_ULong  table2_length )
01693   {
01694     if ( table1_start == table2_start )
01695     {
01696       if ( ( table1_length == 0 || table2_length == 0 ) )
01697         goto Out;
01698     }
01699     else if ( table1_start < table2_start )
01700     {
01701       if ( ( table1_start + table1_length ) <= table2_start )
01702         goto Out;
01703     }
01704     else if ( table1_start > table2_start )
01705     {
01706       if ( ( table1_start >= table2_start + table2_length ) )
01707         goto Out;
01708     }
01709     return 1;
01710 
01711   Out:
01712     return 0;
01713   }
01714 
01715 
01716   FT_LOCAL_DEF( void )
01717   gxv_odtect_add_range( FT_Bytes          start,
01718                         FT_ULong          length,
01719                         const FT_String*  name,
01720                         GXV_odtect_Range  odtect )
01721   {
01722     odtect->range[ odtect->nRanges ].start  = start;
01723     odtect->range[ odtect->nRanges ].length = length;
01724     odtect->range[ odtect->nRanges ].name   = (FT_String*)name;
01725     odtect->nRanges++;
01726   }
01727 
01728 
01729   FT_LOCAL_DEF( void )
01730   gxv_odtect_validate( GXV_odtect_Range  odtect,
01731                        GXV_Validator     valid )
01732   {
01733     FT_UInt  i, j;
01734 
01735 
01736     GXV_NAME_ENTER( "check overlap among multi ranges" );
01737 
01738     for ( i = 0; i < odtect->nRanges; i++ )
01739       for ( j = 0; j < i; j++ )
01740         if ( 0 != gxv_compare_ranges( odtect->range[i].start,
01741                                       odtect->range[i].length,
01742                                       odtect->range[j].start,
01743                                       odtect->range[j].length ) )
01744         {
01745           if ( odtect->range[i].name || odtect->range[j].name )
01746             GXV_TRACE(( "found overlap between range %d and range %d\n",
01747                         i, j ));
01748           else
01749             GXV_TRACE(( "found overlap between `%s' and `%s\'\n",
01750                         odtect->range[i].name,
01751                         odtect->range[j].name ));
01752           FT_INVALID_OFFSET;
01753         }
01754 
01755     GXV_EXIT;
01756   }
01757 
01758 
01759 /* END */

Generated on Tue May 22 2012 04:37:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.