(root)/
freetype-2.13.2/
src/
gxvalid/
gxvtrak.c
       1  /****************************************************************************
       2   *
       3   * gxvtrak.c
       4   *
       5   *   TrueTypeGX/AAT trak 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  gxvtrak
      40  
      41  
      42    /*************************************************************************/
      43    /*************************************************************************/
      44    /*****                                                               *****/
      45    /*****                      Data and Types                           *****/
      46    /*****                                                               *****/
      47    /*************************************************************************/
      48    /*************************************************************************/
      49  
      50      /*
      51       * referred track table format specification:
      52       * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
      53       * last update was 1996.
      54       * ----------------------------------------------
      55       * [MINIMUM HEADER]: GXV_TRAK_SIZE_MIN
      56       * version          (fixed:  32bit) = 0x00010000
      57       * format           (uint16: 16bit) = 0 is only defined (1996)
      58       * horizOffset      (uint16: 16bit)
      59       * vertOffset       (uint16: 16bit)
      60       * reserved         (uint16: 16bit) = 0
      61       * ----------------------------------------------
      62       * [VARIABLE BODY]:
      63       * horizData
      64       *   header         ( 2 + 2 + 4
      65       *   trackTable       + nTracks * ( 4 + 2 + 2 )
      66       *   sizeTable        + nSizes * 4 )
      67       * ----------------------------------------------
      68       * vertData
      69       *   header         ( 2 + 2 + 4
      70       *   trackTable       + nTracks * ( 4 + 2 + 2 )
      71       *   sizeTable        + nSizes * 4 )
      72       * ----------------------------------------------
      73       */
      74    typedef struct  GXV_trak_DataRec_
      75    {
      76      FT_UShort  trackValueOffset_min;
      77      FT_UShort  trackValueOffset_max;
      78  
      79    } GXV_trak_DataRec, *GXV_trak_Data;
      80  
      81  
      82  #define GXV_TRAK_DATA( FIELD )  GXV_TABLE_DATA( trak, FIELD )
      83  
      84  
      85    /*************************************************************************/
      86    /*************************************************************************/
      87    /*****                                                               *****/
      88    /*****                      UTILITY FUNCTIONS                        *****/
      89    /*****                                                               *****/
      90    /*************************************************************************/
      91    /*************************************************************************/
      92  
      93    static void
      94    gxv_trak_trackTable_validate( FT_Bytes       table,
      95                                  FT_Bytes       limit,
      96                                  FT_UShort      nTracks,
      97                                  GXV_Validator  gxvalid )
      98    {
      99      FT_Bytes  p = table;
     100  
     101      FT_Fixed   track, t;
     102      FT_UShort  nameIndex;
     103      FT_UShort  offset;
     104      FT_UShort  i, j;
     105  
     106  
     107      GXV_NAME_ENTER( "trackTable" );
     108  
     109      GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFFU;
     110      GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000;
     111  
     112      GXV_LIMIT_CHECK( nTracks * ( 4 + 2 + 2 ) );
     113  
     114      for ( i = 0; i < nTracks; i++ )
     115      {
     116        p = table + i * ( 4 + 2 + 2 );
     117        track     = FT_NEXT_LONG( p );
     118        nameIndex = FT_NEXT_USHORT( p );
     119        offset    = FT_NEXT_USHORT( p );
     120  
     121        if ( offset < GXV_TRAK_DATA( trackValueOffset_min ) )
     122          GXV_TRAK_DATA( trackValueOffset_min ) = offset;
     123        if ( offset > GXV_TRAK_DATA( trackValueOffset_max ) )
     124          GXV_TRAK_DATA( trackValueOffset_max ) = offset;
     125  
     126        gxv_sfntName_validate( nameIndex, 256, 32767, gxvalid );
     127  
     128        for ( j = i; j < nTracks; j++ )
     129        {
     130           p = table + j * ( 4 + 2 + 2 );
     131           t = FT_NEXT_LONG( p );
     132           if ( t == track )
     133             GXV_TRACE(( "duplicated entries found for track value 0x%lx\n",
     134                          track ));
     135        }
     136      }
     137  
     138      gxvalid->subtable_length = (FT_ULong)( p - table );
     139      GXV_EXIT;
     140    }
     141  
     142  
     143    static void
     144    gxv_trak_trackData_validate( FT_Bytes       table,
     145                                 FT_Bytes       limit,
     146                                 GXV_Validator  gxvalid )
     147    {
     148      FT_Bytes   p = table;
     149      FT_UShort  nTracks;
     150      FT_UShort  nSizes;
     151      FT_ULong   sizeTableOffset;
     152  
     153      GXV_ODTECT( 4, odtect );
     154  
     155  
     156      GXV_ODTECT_INIT( odtect );
     157      GXV_NAME_ENTER( "trackData" );
     158  
     159      /* read the header of trackData */
     160      GXV_LIMIT_CHECK( 2 + 2 + 4 );
     161      nTracks         = FT_NEXT_USHORT( p );
     162      nSizes          = FT_NEXT_USHORT( p );
     163      sizeTableOffset = FT_NEXT_ULONG( p );
     164  
     165      gxv_odtect_add_range( table, (FT_ULong)( p - table ),
     166                            "trackData header", odtect );
     167  
     168      /* validate trackTable */
     169      gxv_trak_trackTable_validate( p, limit, nTracks, gxvalid );
     170      gxv_odtect_add_range( p, gxvalid->subtable_length,
     171                            "trackTable", odtect );
     172  
     173      /* sizeTable is array of FT_Fixed, don't check contents */
     174      p = gxvalid->root->base + sizeTableOffset;
     175      GXV_LIMIT_CHECK( nSizes * 4 );
     176      gxv_odtect_add_range( p, nSizes * 4, "sizeTable", odtect );
     177  
     178      /* validate trackValueOffet */
     179      p = gxvalid->root->base + GXV_TRAK_DATA( trackValueOffset_min );
     180      if ( limit - p < nTracks * nSizes * 2 )
     181        GXV_TRACE(( "too short trackValue array\n" ));
     182  
     183      p = gxvalid->root->base + GXV_TRAK_DATA( trackValueOffset_max );
     184      GXV_LIMIT_CHECK( nSizes * 2 );
     185  
     186      gxv_odtect_add_range( gxvalid->root->base
     187                              + GXV_TRAK_DATA( trackValueOffset_min ),
     188                            GXV_TRAK_DATA( trackValueOffset_max )
     189                              - GXV_TRAK_DATA( trackValueOffset_min )
     190                              + nSizes * 2,
     191                            "trackValue array", odtect );
     192  
     193      gxv_odtect_validate( odtect, gxvalid );
     194  
     195      GXV_EXIT;
     196    }
     197  
     198  
     199    /*************************************************************************/
     200    /*************************************************************************/
     201    /*****                                                               *****/
     202    /*****                          trak TABLE                           *****/
     203    /*****                                                               *****/
     204    /*************************************************************************/
     205    /*************************************************************************/
     206  
     207    FT_LOCAL_DEF( void )
     208    gxv_trak_validate( FT_Bytes      table,
     209                       FT_Face       face,
     210                       FT_Validator  ftvalid )
     211    {
     212      FT_Bytes          p = table;
     213      FT_Bytes          limit = 0;
     214  
     215      GXV_ValidatorRec  gxvalidrec;
     216      GXV_Validator     gxvalid = &gxvalidrec;
     217      GXV_trak_DataRec  trakrec;
     218      GXV_trak_Data     trak = &trakrec;
     219  
     220      FT_ULong   version;
     221      FT_UShort  format;
     222      FT_UShort  horizOffset;
     223      FT_UShort  vertOffset;
     224      FT_UShort  reserved;
     225  
     226  
     227      GXV_ODTECT( 3, odtect );
     228  
     229      GXV_ODTECT_INIT( odtect );
     230      gxvalid->root       = ftvalid;
     231      gxvalid->table_data = trak;
     232      gxvalid->face       = face;
     233  
     234      limit      = gxvalid->root->limit;
     235  
     236      FT_TRACE3(( "validating `trak' table\n" ));
     237      GXV_INIT;
     238  
     239      GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 + 2 );
     240      version     = FT_NEXT_ULONG( p );
     241      format      = FT_NEXT_USHORT( p );
     242      horizOffset = FT_NEXT_USHORT( p );
     243      vertOffset  = FT_NEXT_USHORT( p );
     244      reserved    = FT_NEXT_USHORT( p );
     245  
     246      GXV_TRACE(( " (version = 0x%08lx)\n", version ));
     247      GXV_TRACE(( " (format = 0x%04x)\n", format ));
     248      GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset ));
     249      GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset ));
     250      GXV_TRACE(( " (reserved = 0x%04x)\n", reserved ));
     251  
     252      /* Version 1.0 (always:1996) */
     253      if ( version != 0x00010000UL )
     254        FT_INVALID_FORMAT;
     255  
     256      /* format 0 (always:1996) */
     257      if ( format != 0x0000 )
     258        FT_INVALID_FORMAT;
     259  
     260      GXV_32BIT_ALIGNMENT_VALIDATE( horizOffset );
     261      GXV_32BIT_ALIGNMENT_VALIDATE( vertOffset );
     262  
     263      /* Reserved Fixed Value (always) */
     264      if ( reserved != 0x0000 )
     265        FT_INVALID_DATA;
     266  
     267      /* validate trackData */
     268      if ( 0 < horizOffset )
     269      {
     270        gxv_trak_trackData_validate( table + horizOffset, limit, gxvalid );
     271        gxv_odtect_add_range( table + horizOffset, gxvalid->subtable_length,
     272                              "horizJustData", odtect );
     273      }
     274  
     275      if ( 0 < vertOffset )
     276      {
     277        gxv_trak_trackData_validate( table + vertOffset, limit, gxvalid );
     278        gxv_odtect_add_range( table + vertOffset, gxvalid->subtable_length,
     279                              "vertJustData", odtect );
     280      }
     281  
     282      gxv_odtect_validate( odtect, gxvalid );
     283  
     284      FT_TRACE4(( "\n" ));
     285    }
     286  
     287  
     288  /* END */