tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gxvfeat.c (9949B)


      1 /****************************************************************************
      2 *
      3 * gxvfeat.c
      4 *
      5 *   TrueTypeGX/AAT feat table validation (body).
      6 *
      7 * Copyright (C) 2004-2025 by
      8 * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
      9 * David Turner, Robert Wilhelm, and Werner Lemberg.
     10 *
     11 * This file is part of the FreeType project, and may only be used,
     12 * modified, and distributed under the terms of the FreeType project
     13 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
     14 * this file you indicate that you have read the license and
     15 * understand and accept it fully.
     16 *
     17 */
     18 
     19 /****************************************************************************
     20 *
     21 * gxvalid is derived from both gxlayout module and otvalid module.
     22 * Development of gxlayout is supported by the Information-technology
     23 * Promotion Agency(IPA), Japan.
     24 *
     25 */
     26 
     27 
     28 #include "gxvalid.h"
     29 #include "gxvcommn.h"
     30 #include "gxvfeat.h"
     31 
     32 
     33  /**************************************************************************
     34   *
     35   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     36   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     37   * messages during execution.
     38   */
     39 #undef  FT_COMPONENT
     40 #define FT_COMPONENT  gxvfeat
     41 
     42 
     43  /*************************************************************************/
     44  /*************************************************************************/
     45  /*****                                                               *****/
     46  /*****                      Data and Types                           *****/
     47  /*****                                                               *****/
     48  /*************************************************************************/
     49  /*************************************************************************/
     50 
     51  typedef struct  GXV_feat_DataRec_
     52  {
     53    FT_UInt    reserved_size;
     54    FT_UShort  feature;
     55    FT_UShort  setting;
     56 
     57  } GXV_feat_DataRec, *GXV_feat_Data;
     58 
     59 
     60 #define GXV_FEAT_DATA( field )  GXV_TABLE_DATA( feat, field )
     61 
     62 
     63  typedef enum  GXV_FeatureFlagsMask_
     64  {
     65    GXV_FEAT_MASK_EXCLUSIVE_SETTINGS = 0x8000U,
     66    GXV_FEAT_MASK_DYNAMIC_DEFAULT    = 0x4000,
     67    GXV_FEAT_MASK_UNUSED             = 0x3F00,
     68    GXV_FEAT_MASK_DEFAULT_SETTING    = 0x00FF
     69 
     70  } GXV_FeatureFlagsMask;
     71 
     72 
     73  /*************************************************************************/
     74  /*************************************************************************/
     75  /*****                                                               *****/
     76  /*****                      UTILITY FUNCTIONS                        *****/
     77  /*****                                                               *****/
     78  /*************************************************************************/
     79  /*************************************************************************/
     80 
     81  static void
     82  gxv_feat_registry_validate( FT_UShort      feature,
     83                              FT_UShort      nSettings,
     84                              FT_Bool        exclusive,
     85                              GXV_Validator  gxvalid )
     86  {
     87    GXV_NAME_ENTER( "feature in registry" );
     88 
     89    GXV_TRACE(( " (feature = %u)\n", feature ));
     90 
     91    if ( feature >= gxv_feat_registry_length )
     92    {
     93      GXV_TRACE(( "feature number %d is out of range %lu\n",
     94                  feature, gxv_feat_registry_length ));
     95      GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
     96      goto Exit;
     97    }
     98 
     99    if ( gxv_feat_registry[feature].existence == 0 )
    100    {
    101      GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
    102                  feature ));
    103      GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
    104      goto Exit;
    105    }
    106 
    107    if ( gxv_feat_registry[feature].apple_reserved )
    108    {
    109      /* Don't use here. Apple is reserved. */
    110      GXV_TRACE(( "feature number %d is reserved by Apple\n", feature ));
    111      if ( gxvalid->root->level >= FT_VALIDATE_TIGHT )
    112        FT_INVALID_DATA;
    113    }
    114 
    115    if ( nSettings != gxv_feat_registry[feature].nSettings )
    116    {
    117      GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n",
    118                  feature, nSettings,
    119                  gxv_feat_registry[feature].nSettings ));
    120      if ( gxvalid->root->level >= FT_VALIDATE_TIGHT )
    121        FT_INVALID_DATA;
    122    }
    123 
    124    if ( exclusive != gxv_feat_registry[feature].exclusive )
    125    {
    126      GXV_TRACE(( "exclusive flag %d differs from predefined value\n",
    127                  exclusive ));
    128      if ( gxvalid->root->level >= FT_VALIDATE_TIGHT )
    129        FT_INVALID_DATA;
    130    }
    131 
    132  Exit:
    133    GXV_EXIT;
    134  }
    135 
    136 
    137  static void
    138  gxv_feat_name_index_validate( FT_Bytes       table,
    139                                FT_Bytes       limit,
    140                                GXV_Validator  gxvalid )
    141  {
    142    FT_Bytes  p = table;
    143 
    144    FT_Short  nameIndex;
    145 
    146 
    147    GXV_NAME_ENTER( "nameIndex" );
    148 
    149    GXV_LIMIT_CHECK( 2 );
    150    nameIndex = FT_NEXT_SHORT ( p );
    151    GXV_TRACE(( " (nameIndex = %d)\n", nameIndex ));
    152 
    153    gxv_sfntName_validate( (FT_UShort)nameIndex,
    154                           255,
    155                           32768U,
    156                           gxvalid );
    157 
    158    GXV_EXIT;
    159  }
    160 
    161 
    162  static void
    163  gxv_feat_setting_validate( FT_Bytes       table,
    164                             FT_Bytes       limit,
    165                             FT_Bool        exclusive,
    166                             GXV_Validator  gxvalid )
    167  {
    168    FT_Bytes   p = table;
    169    FT_UShort  setting;
    170 
    171 
    172    GXV_NAME_ENTER( "setting" );
    173 
    174    GXV_LIMIT_CHECK( 2 );
    175 
    176    setting = FT_NEXT_USHORT( p );
    177 
    178    /* If we have exclusive setting, the setting should be odd. */
    179    if ( exclusive && ( setting & 1 ) == 0 )
    180      FT_INVALID_DATA;
    181 
    182    gxv_feat_name_index_validate( p, limit, gxvalid );
    183 
    184    GXV_FEAT_DATA( setting ) = setting;
    185 
    186    GXV_EXIT;
    187  }
    188 
    189 
    190  static void
    191  gxv_feat_name_validate( FT_Bytes       table,
    192                          FT_Bytes       limit,
    193                          GXV_Validator  gxvalid )
    194  {
    195    FT_Bytes   p             = table;
    196    FT_UInt    reserved_size = GXV_FEAT_DATA( reserved_size );
    197 
    198    FT_UShort  feature;
    199    FT_UShort  nSettings;
    200    FT_ULong   settingTable;
    201    FT_UShort  featureFlags;
    202 
    203    FT_Bool    exclusive;
    204    FT_Int     last_setting;
    205    FT_UInt    i;
    206 
    207 
    208    GXV_NAME_ENTER( "name" );
    209 
    210    /* feature + nSettings + settingTable + featureFlags */
    211    GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );
    212 
    213    feature = FT_NEXT_USHORT( p );
    214    GXV_FEAT_DATA( feature ) = feature;
    215 
    216    nSettings    = FT_NEXT_USHORT( p );
    217    settingTable = FT_NEXT_ULONG ( p );
    218    featureFlags = FT_NEXT_USHORT( p );
    219 
    220    if ( settingTable < reserved_size )
    221      FT_INVALID_OFFSET;
    222 
    223    if ( ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
    224      GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
    225 
    226    exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS );
    227    if ( exclusive )
    228    {
    229      FT_Byte  dynamic_default;
    230 
    231 
    232      if ( featureFlags & GXV_FEAT_MASK_DYNAMIC_DEFAULT )
    233        dynamic_default = (FT_Byte)( featureFlags &
    234                                     GXV_FEAT_MASK_DEFAULT_SETTING );
    235      else
    236        dynamic_default = 0;
    237 
    238      /* If exclusive, check whether default setting is in the range. */
    239      if ( !( dynamic_default < nSettings ) )
    240        FT_INVALID_FORMAT;
    241    }
    242 
    243    gxv_feat_registry_validate( feature, nSettings, exclusive, gxvalid );
    244 
    245    gxv_feat_name_index_validate( p, limit, gxvalid );
    246 
    247    p = gxvalid->root->base + settingTable;
    248    for ( last_setting = -1, i = 0; i < nSettings; i++ )
    249    {
    250      gxv_feat_setting_validate( p, limit, exclusive, gxvalid );
    251 
    252      if ( (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
    253        GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
    254 
    255      last_setting = (FT_Int)GXV_FEAT_DATA( setting );
    256      /* setting + nameIndex */
    257      p += ( 2 + 2 );
    258    }
    259 
    260    GXV_EXIT;
    261  }
    262 
    263 
    264  /*************************************************************************/
    265  /*************************************************************************/
    266  /*****                                                               *****/
    267  /*****                         feat TABLE                            *****/
    268  /*****                                                               *****/
    269  /*************************************************************************/
    270  /*************************************************************************/
    271 
    272  FT_LOCAL_DEF( void )
    273  gxv_feat_validate( FT_Bytes      table,
    274                     FT_Face       face,
    275                     FT_Validator  ftvalid )
    276  {
    277    GXV_ValidatorRec  gxvalidrec;
    278    GXV_Validator     gxvalid = &gxvalidrec;
    279 
    280    GXV_feat_DataRec  featrec;
    281    GXV_feat_Data     feat = &featrec;
    282 
    283    FT_Bytes          p     = table;
    284    FT_Bytes          limit = 0;
    285 
    286    FT_UInt           featureNameCount;
    287 
    288    FT_UInt           i;
    289    FT_Int            last_feature;
    290 
    291 
    292    gxvalid->root       = ftvalid;
    293    gxvalid->table_data = feat;
    294    gxvalid->face       = face;
    295 
    296    FT_TRACE3(( "validating `feat' table\n" ));
    297    GXV_INIT;
    298 
    299    feat->reserved_size = 0;
    300 
    301    /* version + featureNameCount + none_0 + none_1  */
    302    GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
    303    feat->reserved_size += 4 + 2 + 2 + 4;
    304 
    305    if ( FT_NEXT_ULONG( p ) != 0x00010000UL ) /* Version */
    306      FT_INVALID_FORMAT;
    307 
    308    featureNameCount = FT_NEXT_USHORT( p );
    309    GXV_TRACE(( " (featureNameCount = %u)\n", featureNameCount ));
    310 
    311    if ( !( IS_PARANOID_VALIDATION ) )
    312      p += 6; /* skip (none) and (none) */
    313    else
    314    {
    315      if ( FT_NEXT_USHORT( p ) != 0 )
    316        FT_INVALID_DATA;
    317 
    318      if ( FT_NEXT_ULONG( p )  != 0 )
    319        FT_INVALID_DATA;
    320    }
    321 
    322    feat->reserved_size += featureNameCount * ( 2 + 2 + 4 + 2 + 2 );
    323 
    324    for ( last_feature = -1, i = 0; i < featureNameCount; i++ )
    325    {
    326      gxv_feat_name_validate( p, limit, gxvalid );
    327 
    328      if ( (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
    329        GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
    330 
    331      last_feature = GXV_FEAT_DATA( feature );
    332      p += 2 + 2 + 4 + 2 + 2;
    333    }
    334 
    335    FT_TRACE4(( "\n" ));
    336  }
    337 
    338 
    339 /* END */