tor-browser

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

gxvprop.c (10208B)


      1 /****************************************************************************
      2 *
      3 * gxvprop.c
      4 *
      5 *   TrueTypeGX/AAT prop 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 
     31 
     32  /**************************************************************************
     33   *
     34   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     35   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     36   * messages during execution.
     37   */
     38 #undef  FT_COMPONENT
     39 #define FT_COMPONENT  gxvprop
     40 
     41 
     42  /*************************************************************************/
     43  /*************************************************************************/
     44  /*****                                                               *****/
     45  /*****                      Data and Types                           *****/
     46  /*****                                                               *****/
     47  /*************************************************************************/
     48  /*************************************************************************/
     49 
     50 #define GXV_PROP_HEADER_SIZE  ( 4 + 2 + 2 )
     51 #define GXV_PROP_SIZE_MIN     GXV_PROP_HEADER_SIZE
     52 
     53  typedef struct  GXV_prop_DataRec_
     54  {
     55    FT_Fixed  version;
     56 
     57  } GXV_prop_DataRec, *GXV_prop_Data;
     58 
     59 #define GXV_PROP_DATA( field )  GXV_TABLE_DATA( prop, field )
     60 
     61 #define GXV_PROP_FLOATER                      0x8000U
     62 #define GXV_PROP_USE_COMPLEMENTARY_BRACKET    0x1000U
     63 #define GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET 0x0F00U
     64 #define GXV_PROP_ATTACHING_TO_RIGHT           0x0080U
     65 #define GXV_PROP_RESERVED                     0x0060U
     66 #define GXV_PROP_DIRECTIONALITY_CLASS         0x001FU
     67 
     68 
     69  /*************************************************************************/
     70  /*************************************************************************/
     71  /*****                                                               *****/
     72  /*****                      UTILITY FUNCTIONS                        *****/
     73  /*****                                                               *****/
     74  /*************************************************************************/
     75  /*************************************************************************/
     76 
     77  static void
     78  gxv_prop_zero_advance_validate( FT_UShort      gid,
     79                                  GXV_Validator  gxvalid )
     80  {
     81    FT_Face       face;
     82    FT_Error      error;
     83    FT_GlyphSlot  glyph;
     84 
     85 
     86    GXV_NAME_ENTER( "zero advance" );
     87 
     88    face = gxvalid->face;
     89 
     90    error = FT_Load_Glyph( face,
     91                           gid,
     92                           FT_LOAD_IGNORE_TRANSFORM );
     93    if ( error )
     94      FT_INVALID_GLYPH_ID;
     95 
     96    glyph = face->glyph;
     97 
     98    if ( glyph->advance.x != (FT_Pos)0 ||
     99         glyph->advance.y != (FT_Pos)0 )
    100    {
    101      GXV_TRACE(( "  found non-zero advance in zero-advance glyph\n" ));
    102      FT_INVALID_DATA;
    103    }
    104 
    105    GXV_EXIT;
    106  }
    107 
    108 
    109  /* Pass 0 as GLYPH to check the default property */
    110  static void
    111  gxv_prop_property_validate( FT_UShort      property,
    112                              FT_UShort      glyph,
    113                              GXV_Validator  gxvalid )
    114  {
    115    if ( glyph != 0 && ( property & GXV_PROP_FLOATER ) )
    116      gxv_prop_zero_advance_validate( glyph, gxvalid );
    117 
    118    if ( property & GXV_PROP_USE_COMPLEMENTARY_BRACKET )
    119    {
    120      FT_UShort  offset;
    121      char       complement;
    122 
    123 
    124      offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET );
    125      if ( offset == 0 )
    126      {
    127        GXV_TRACE(( "  found zero offset to property\n" ));
    128        FT_INVALID_OFFSET;
    129      }
    130 
    131      complement = (char)( offset >> 8 );
    132      if ( complement & 0x08 )
    133      {
    134        /* Top bit is set: negative */
    135 
    136        /* Calculate the absolute offset */
    137        complement = (char)( ( complement & 0x07 ) + 1 );
    138 
    139        /* The gid for complement must be greater than 0 */
    140        if ( glyph <= complement )
    141        {
    142          GXV_TRACE(( "  found non-positive glyph complement\n" ));
    143          FT_INVALID_DATA;
    144        }
    145      }
    146      else
    147      {
    148        /* The gid for complement must be the face. */
    149        gxv_glyphid_validate( (FT_UShort)( glyph + complement ), gxvalid );
    150      }
    151    }
    152    else
    153    {
    154      if ( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET )
    155        GXV_TRACE(( "glyph %d cannot have complementary bracketing\n",
    156                    glyph ));
    157    }
    158 
    159    /* this is introduced in version 2.0 */
    160    if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
    161    {
    162      if ( GXV_PROP_DATA( version ) == 0x00010000UL )
    163      {
    164        GXV_TRACE(( "  found older version (1.0) in new version table\n" ));
    165        FT_INVALID_DATA;
    166      }
    167    }
    168 
    169    if ( property & GXV_PROP_RESERVED )
    170    {
    171      GXV_TRACE(( "  found non-zero bits in reserved bits\n" ));
    172      FT_INVALID_DATA;
    173    }
    174 
    175    if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
    176    {
    177      /* TODO: Too restricted. Use the validation level. */
    178      if ( GXV_PROP_DATA( version ) == 0x00010000UL ||
    179           GXV_PROP_DATA( version ) == 0x00020000UL )
    180      {
    181        GXV_TRACE(( "  found too old version in directionality class\n" ));
    182        FT_INVALID_DATA;
    183      }
    184    }
    185  }
    186 
    187 
    188  static void
    189  gxv_prop_LookupValue_validate( FT_UShort            glyph,
    190                                 GXV_LookupValueCPtr  value_p,
    191                                 GXV_Validator        gxvalid )
    192  {
    193    gxv_prop_property_validate( value_p->u, glyph, gxvalid );
    194  }
    195 
    196 
    197  /*
    198    +===============+ --------+
    199    | lookup header |         |
    200    +===============+         |
    201    | BinSrchHeader |         |
    202    +===============+         |
    203    | lastGlyph[0]  |         |
    204    +---------------+         |
    205    | firstGlyph[0] |         |    head of lookup table
    206    +---------------+         |             +
    207    | offset[0]     |    ->   |          offset            [byte]
    208    +===============+         |             +
    209    | lastGlyph[1]  |         | (glyphID - firstGlyph) * 2 [byte]
    210    +---------------+         |
    211    | firstGlyph[1] |         |
    212    +---------------+         |
    213    | offset[1]     |         |
    214    +===============+         |
    215                              |
    216     ...                      |
    217                              |
    218    16bit value array         |
    219    +===============+         |
    220    |     value     | <-------+
    221    ...
    222  */
    223 
    224  static GXV_LookupValueDesc
    225  gxv_prop_LookupFmt4_transit( FT_UShort            relative_gindex,
    226                               GXV_LookupValueCPtr  base_value_p,
    227                               FT_Bytes             lookuptbl_limit,
    228                               GXV_Validator        gxvalid )
    229  {
    230    FT_Bytes             p;
    231    FT_Bytes             limit;
    232    FT_UShort            offset;
    233    GXV_LookupValueDesc  value;
    234 
    235    /* XXX: check range? */
    236    offset = (FT_UShort)( base_value_p->u +
    237                          relative_gindex * sizeof ( FT_UShort ) );
    238    p      = gxvalid->lookuptbl_head + offset;
    239    limit  = lookuptbl_limit;
    240 
    241    GXV_LIMIT_CHECK ( 2 );
    242    value.u = FT_NEXT_USHORT( p );
    243 
    244    return value;
    245  }
    246 
    247 
    248  /*************************************************************************/
    249  /*************************************************************************/
    250  /*****                                                               *****/
    251  /*****                         prop TABLE                            *****/
    252  /*****                                                               *****/
    253  /*************************************************************************/
    254  /*************************************************************************/
    255 
    256  FT_LOCAL_DEF( void )
    257  gxv_prop_validate( FT_Bytes      table,
    258                     FT_Face       face,
    259                     FT_Validator  ftvalid )
    260  {
    261    FT_Bytes          p     = table;
    262    FT_Bytes          limit = 0;
    263    GXV_ValidatorRec  gxvalidrec;
    264    GXV_Validator     gxvalid = &gxvalidrec;
    265 
    266    GXV_prop_DataRec  proprec;
    267    GXV_prop_Data     prop = &proprec;
    268 
    269    FT_Fixed          version;
    270    FT_UShort         format;
    271    FT_UShort         defaultProp;
    272 
    273 
    274    gxvalid->root       = ftvalid;
    275    gxvalid->table_data = prop;
    276    gxvalid->face       = face;
    277 
    278    FT_TRACE3(( "validating `prop' table\n" ));
    279    GXV_INIT;
    280 
    281    GXV_LIMIT_CHECK( 4 + 2 + 2 );
    282    version     = FT_NEXT_LONG( p );
    283    format      = FT_NEXT_USHORT( p );
    284    defaultProp = FT_NEXT_USHORT( p );
    285 
    286    GXV_TRACE(( "  version 0x%08lx\n", version ));
    287    GXV_TRACE(( "  format  0x%04x\n", format ));
    288    GXV_TRACE(( "  defaultProp  0x%04x\n", defaultProp ));
    289 
    290    /* only versions 1.0, 2.0, 3.0 are defined (1996) */
    291    if ( version != 0x00010000UL &&
    292         version != 0x00020000UL &&
    293         version != 0x00030000UL )
    294    {
    295      GXV_TRACE(( "  found unknown version\n" ));
    296      FT_INVALID_FORMAT;
    297    }
    298 
    299 
    300    /* only formats 0x0000, 0x0001 are defined (1996) */
    301    if ( format > 1 )
    302    {
    303      GXV_TRACE(( "  found unknown format\n" ));
    304      FT_INVALID_FORMAT;
    305    }
    306 
    307    gxv_prop_property_validate( defaultProp, 0, gxvalid );
    308 
    309    if ( format == 0 )
    310    {
    311      FT_TRACE3(( "(format 0, no per-glyph properties, "
    312                  "remaining %ld bytes are skipped)", limit - p ));
    313      goto Exit;
    314    }
    315 
    316    /* format == 1 */
    317    GXV_PROP_DATA( version ) = version;
    318 
    319    gxvalid->lookupval_sign   = GXV_LOOKUPVALUE_UNSIGNED;
    320    gxvalid->lookupval_func   = gxv_prop_LookupValue_validate;
    321    gxvalid->lookupfmt4_trans = gxv_prop_LookupFmt4_transit;
    322 
    323    gxv_LookupTable_validate( p, limit, gxvalid );
    324 
    325  Exit:
    326    FT_TRACE4(( "\n" ));
    327  }
    328 
    329 
    330 /* END */