(root)/
freetype-2.13.2/
src/
otvalid/
otvbase.c
       1  /****************************************************************************
       2   *
       3   * otvbase.c
       4   *
       5   *   OpenType BASE table validation (body).
       6   *
       7   * Copyright (C) 2004-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * This file is part of the FreeType project, and may only be used,
      11   * modified, and distributed under the terms of the FreeType project
      12   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      13   * this file you indicate that you have read the license and
      14   * understand and accept it fully.
      15   *
      16   */
      17  
      18  
      19  #include "otvalid.h"
      20  #include "otvcommn.h"
      21  
      22  
      23    /**************************************************************************
      24     *
      25     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
      26     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
      27     * messages during execution.
      28     */
      29  #undef  FT_COMPONENT
      30  #define FT_COMPONENT  otvbase
      31  
      32  
      33    static void
      34    otv_BaseCoord_validate( FT_Bytes       table,
      35                            OTV_Validator  otvalid )
      36    {
      37      FT_Bytes  p = table;
      38      FT_UInt   BaseCoordFormat;
      39  
      40  
      41      OTV_NAME_ENTER( "BaseCoord" );
      42  
      43      OTV_LIMIT_CHECK( 4 );
      44      BaseCoordFormat = FT_NEXT_USHORT( p );
      45      p += 2;     /* skip Coordinate */
      46  
      47      OTV_TRACE(( " (format %d)\n", BaseCoordFormat ));
      48  
      49      switch ( BaseCoordFormat )
      50      {
      51      case 1:     /* BaseCoordFormat1 */
      52        break;
      53  
      54      case 2:     /* BaseCoordFormat2 */
      55        OTV_LIMIT_CHECK( 4 );   /* ReferenceGlyph, BaseCoordPoint */
      56        break;
      57  
      58      case 3:     /* BaseCoordFormat3 */
      59        OTV_LIMIT_CHECK( 2 );
      60        /* DeviceTable */
      61        otv_Device_validate( table + FT_NEXT_USHORT( p ), otvalid );
      62        break;
      63  
      64      default:
      65        FT_INVALID_FORMAT;
      66      }
      67  
      68      OTV_EXIT;
      69    }
      70  
      71  
      72    static void
      73    otv_BaseTagList_validate( FT_Bytes       table,
      74                              OTV_Validator  otvalid )
      75    {
      76      FT_Bytes  p = table;
      77      FT_UInt   BaseTagCount;
      78  
      79  
      80      OTV_NAME_ENTER( "BaseTagList" );
      81  
      82      OTV_LIMIT_CHECK( 2 );
      83  
      84      BaseTagCount = FT_NEXT_USHORT( p );
      85  
      86      OTV_TRACE(( " (BaseTagCount = %d)\n", BaseTagCount ));
      87  
      88      OTV_LIMIT_CHECK( BaseTagCount * 4 );          /* BaselineTag */
      89  
      90      OTV_EXIT;
      91    }
      92  
      93  
      94    static void
      95    otv_BaseValues_validate( FT_Bytes       table,
      96                             OTV_Validator  otvalid )
      97    {
      98      FT_Bytes  p = table;
      99      FT_UInt   BaseCoordCount;
     100  
     101  
     102      OTV_NAME_ENTER( "BaseValues" );
     103  
     104      OTV_LIMIT_CHECK( 4 );
     105  
     106      p             += 2;                     /* skip DefaultIndex */
     107      BaseCoordCount = FT_NEXT_USHORT( p );
     108  
     109      OTV_TRACE(( " (BaseCoordCount = %d)\n", BaseCoordCount ));
     110  
     111      OTV_LIMIT_CHECK( BaseCoordCount * 2 );
     112  
     113      /* BaseCoord */
     114      for ( ; BaseCoordCount > 0; BaseCoordCount-- )
     115        otv_BaseCoord_validate( table + FT_NEXT_USHORT( p ), otvalid );
     116  
     117      OTV_EXIT;
     118    }
     119  
     120  
     121    static void
     122    otv_MinMax_validate( FT_Bytes       table,
     123                         OTV_Validator  otvalid )
     124    {
     125      FT_Bytes  p = table;
     126      FT_UInt   table_size;
     127      FT_UInt   FeatMinMaxCount;
     128  
     129      OTV_OPTIONAL_TABLE( MinCoord );
     130      OTV_OPTIONAL_TABLE( MaxCoord );
     131  
     132  
     133      OTV_NAME_ENTER( "MinMax" );
     134  
     135      OTV_LIMIT_CHECK( 6 );
     136  
     137      OTV_OPTIONAL_OFFSET( MinCoord );
     138      OTV_OPTIONAL_OFFSET( MaxCoord );
     139      FeatMinMaxCount = FT_NEXT_USHORT( p );
     140  
     141      OTV_TRACE(( " (FeatMinMaxCount = %d)\n", FeatMinMaxCount ));
     142  
     143      table_size = FeatMinMaxCount * 8 + 6;
     144  
     145      OTV_SIZE_CHECK( MinCoord );
     146      if ( MinCoord )
     147        otv_BaseCoord_validate( table + MinCoord, otvalid );
     148  
     149      OTV_SIZE_CHECK( MaxCoord );
     150      if ( MaxCoord )
     151        otv_BaseCoord_validate( table + MaxCoord, otvalid );
     152  
     153      OTV_LIMIT_CHECK( FeatMinMaxCount * 8 );
     154  
     155      /* FeatMinMaxRecord */
     156      for ( ; FeatMinMaxCount > 0; FeatMinMaxCount-- )
     157      {
     158        p += 4;                           /* skip FeatureTableTag */
     159  
     160        OTV_OPTIONAL_OFFSET( MinCoord );
     161        OTV_OPTIONAL_OFFSET( MaxCoord );
     162  
     163        OTV_SIZE_CHECK( MinCoord );
     164        if ( MinCoord )
     165          otv_BaseCoord_validate( table + MinCoord, otvalid );
     166  
     167        OTV_SIZE_CHECK( MaxCoord );
     168        if ( MaxCoord )
     169          otv_BaseCoord_validate( table + MaxCoord, otvalid );
     170      }
     171  
     172      OTV_EXIT;
     173    }
     174  
     175  
     176    static void
     177    otv_BaseScript_validate( FT_Bytes       table,
     178                             OTV_Validator  otvalid )
     179    {
     180      FT_Bytes  p = table;
     181      FT_UInt   table_size;
     182      FT_UInt   BaseLangSysCount;
     183  
     184      OTV_OPTIONAL_TABLE( BaseValues    );
     185      OTV_OPTIONAL_TABLE( DefaultMinMax );
     186  
     187  
     188      OTV_NAME_ENTER( "BaseScript" );
     189  
     190      OTV_LIMIT_CHECK( 6 );
     191      OTV_OPTIONAL_OFFSET( BaseValues    );
     192      OTV_OPTIONAL_OFFSET( DefaultMinMax );
     193      BaseLangSysCount = FT_NEXT_USHORT( p );
     194  
     195      OTV_TRACE(( " (BaseLangSysCount = %d)\n", BaseLangSysCount ));
     196  
     197      table_size = BaseLangSysCount * 6 + 6;
     198  
     199      OTV_SIZE_CHECK( BaseValues );
     200      if ( BaseValues )
     201        otv_BaseValues_validate( table + BaseValues, otvalid );
     202  
     203      OTV_SIZE_CHECK( DefaultMinMax );
     204      if ( DefaultMinMax )
     205        otv_MinMax_validate( table + DefaultMinMax, otvalid );
     206  
     207      OTV_LIMIT_CHECK( BaseLangSysCount * 6 );
     208  
     209      /* BaseLangSysRecord */
     210      for ( ; BaseLangSysCount > 0; BaseLangSysCount-- )
     211      {
     212        p += 4;       /* skip BaseLangSysTag */
     213  
     214        otv_MinMax_validate( table + FT_NEXT_USHORT( p ), otvalid );
     215      }
     216  
     217      OTV_EXIT;
     218    }
     219  
     220  
     221    static void
     222    otv_BaseScriptList_validate( FT_Bytes       table,
     223                                 OTV_Validator  otvalid )
     224    {
     225      FT_Bytes  p = table;
     226      FT_UInt   BaseScriptCount;
     227  
     228  
     229      OTV_NAME_ENTER( "BaseScriptList" );
     230  
     231      OTV_LIMIT_CHECK( 2 );
     232      BaseScriptCount = FT_NEXT_USHORT( p );
     233  
     234      OTV_TRACE(( " (BaseScriptCount = %d)\n", BaseScriptCount ));
     235  
     236      OTV_LIMIT_CHECK( BaseScriptCount * 6 );
     237  
     238      /* BaseScriptRecord */
     239      for ( ; BaseScriptCount > 0; BaseScriptCount-- )
     240      {
     241        p += 4;       /* skip BaseScriptTag */
     242  
     243        /* BaseScript */
     244        otv_BaseScript_validate( table + FT_NEXT_USHORT( p ), otvalid );
     245      }
     246  
     247      OTV_EXIT;
     248    }
     249  
     250  
     251    static void
     252    otv_Axis_validate( FT_Bytes       table,
     253                       OTV_Validator  otvalid )
     254    {
     255      FT_Bytes  p = table;
     256      FT_UInt   table_size;
     257  
     258      OTV_OPTIONAL_TABLE( BaseTagList );
     259  
     260  
     261      OTV_NAME_ENTER( "Axis" );
     262  
     263      OTV_LIMIT_CHECK( 4 );
     264      OTV_OPTIONAL_OFFSET( BaseTagList );
     265  
     266      table_size = 4;
     267  
     268      OTV_SIZE_CHECK( BaseTagList );
     269      if ( BaseTagList )
     270        otv_BaseTagList_validate( table + BaseTagList, otvalid );
     271  
     272      /* BaseScriptList */
     273      otv_BaseScriptList_validate( table + FT_NEXT_USHORT( p ), otvalid );
     274  
     275      OTV_EXIT;
     276    }
     277  
     278  
     279    FT_LOCAL_DEF( void )
     280    otv_BASE_validate( FT_Bytes      table,
     281                       FT_Validator  ftvalid )
     282    {
     283      OTV_ValidatorRec  otvalidrec;
     284      OTV_Validator     otvalid = &otvalidrec;
     285      FT_Bytes          p       = table;
     286      FT_UInt           table_size;
     287      FT_UShort         version;
     288  
     289      OTV_OPTIONAL_TABLE( HorizAxis );
     290      OTV_OPTIONAL_TABLE( VertAxis  );
     291  
     292      OTV_OPTIONAL_TABLE32( itemVarStore );
     293  
     294  
     295      otvalid->root = ftvalid;
     296  
     297      FT_TRACE3(( "validating BASE table\n" ));
     298      OTV_INIT;
     299  
     300      OTV_LIMIT_CHECK( 4 );
     301  
     302      if ( FT_NEXT_USHORT( p ) != 1 )  /* majorVersion */
     303        FT_INVALID_FORMAT;
     304  
     305      version = FT_NEXT_USHORT( p );   /* minorVersion */
     306  
     307      table_size = 8;
     308      switch ( version )
     309      {
     310      case 0:
     311        OTV_LIMIT_CHECK( 4 );
     312        break;
     313  
     314      case 1:
     315        OTV_LIMIT_CHECK( 8 );
     316        table_size += 4;
     317        break;
     318  
     319      default:
     320        FT_INVALID_FORMAT;
     321      }
     322  
     323      OTV_OPTIONAL_OFFSET( HorizAxis );
     324      OTV_SIZE_CHECK( HorizAxis );
     325      if ( HorizAxis )
     326        otv_Axis_validate( table + HorizAxis, otvalid );
     327  
     328      OTV_OPTIONAL_OFFSET( VertAxis );
     329      OTV_SIZE_CHECK( VertAxis );
     330      if ( VertAxis )
     331        otv_Axis_validate( table + VertAxis, otvalid );
     332  
     333      if ( version > 0 )
     334      {
     335        OTV_OPTIONAL_OFFSET32( itemVarStore );
     336        OTV_SIZE_CHECK32( itemVarStore );
     337        if ( itemVarStore )
     338          OTV_TRACE(( "  [omitting itemVarStore validation]\n" )); /* XXX */
     339      }
     340  
     341      FT_TRACE4(( "\n" ));
     342    }
     343  
     344  
     345  /* END */