(root)/
freetype-2.13.2/
src/
gxvalid/
gxvprop.c
       1  /****************************************************************************
       2   *
       3   * gxvprop.c
       4   *
       5   *   TrueTypeGX/AAT prop table validation (body).
       6   *
       7   * Copyright (C) 2004-2023 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 */