(root)/
freetype-2.13.2/
src/
otvalid/
otvmath.c
       1  /****************************************************************************
       2   *
       3   * otvmath.c
       4   *
       5   *   OpenType MATH table validation (body).
       6   *
       7   * Copyright (C) 2007-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * Written by George Williams.
      11   *
      12   * This file is part of the FreeType project, and may only be used,
      13   * modified, and distributed under the terms of the FreeType project
      14   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      15   * this file you indicate that you have read the license and
      16   * understand and accept it fully.
      17   *
      18   */
      19  
      20  
      21  #include "otvalid.h"
      22  #include "otvcommn.h"
      23  #include "otvgpos.h"
      24  
      25  
      26    /**************************************************************************
      27     *
      28     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
      29     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
      30     * messages during execution.
      31     */
      32  #undef  FT_COMPONENT
      33  #define FT_COMPONENT  otvmath
      34  
      35  
      36  
      37    /*************************************************************************/
      38    /*************************************************************************/
      39    /*****                                                               *****/
      40    /*****                  MATH TYPOGRAPHIC CONSTANTS                   *****/
      41    /*****                                                               *****/
      42    /*************************************************************************/
      43    /*************************************************************************/
      44  
      45    static void
      46    otv_MathConstants_validate( FT_Bytes       table,
      47                                OTV_Validator  otvalid )
      48    {
      49      FT_Bytes  p = table;
      50      FT_UInt   i;
      51      FT_UInt   table_size;
      52  
      53      OTV_OPTIONAL_TABLE( DeviceTableOffset );
      54  
      55  
      56      OTV_NAME_ENTER( "MathConstants" );
      57  
      58      /* 56 constants, 51 have device tables */
      59      OTV_LIMIT_CHECK( 2 * ( 56 + 51 ) );
      60      table_size = 2 * ( 56 + 51 );
      61  
      62      p += 4 * 2;                 /* First 4 constants have no device tables */
      63      for ( i = 0; i < 51; i++ )
      64      {
      65        p += 2;                                            /* skip the value */
      66        OTV_OPTIONAL_OFFSET( DeviceTableOffset );
      67        OTV_SIZE_CHECK( DeviceTableOffset );
      68        if ( DeviceTableOffset )
      69          otv_Device_validate( table + DeviceTableOffset, otvalid );
      70      }
      71  
      72      OTV_EXIT;
      73    }
      74  
      75  
      76    /*************************************************************************/
      77    /*************************************************************************/
      78    /*****                                                               *****/
      79    /*****                   MATH ITALICS CORRECTION                     *****/
      80    /*****                 MATH TOP ACCENT ATTACHMENT                    *****/
      81    /*****                                                               *****/
      82    /*************************************************************************/
      83    /*************************************************************************/
      84  
      85    static void
      86    otv_MathItalicsCorrectionInfo_validate( FT_Bytes       table,
      87                                            OTV_Validator  otvalid,
      88                                            FT_Int         isItalic )
      89    {
      90      FT_Bytes  p = table;
      91      FT_UInt   i, cnt, table_size;
      92  
      93      OTV_OPTIONAL_TABLE( Coverage );
      94      OTV_OPTIONAL_TABLE( DeviceTableOffset );
      95  
      96      FT_UNUSED( isItalic );  /* only used if tracing is active */
      97  
      98  
      99      OTV_NAME_ENTER( isItalic ? "MathItalicsCorrectionInfo"
     100                               : "MathTopAccentAttachment" );
     101  
     102      OTV_LIMIT_CHECK( 4 );
     103  
     104      OTV_OPTIONAL_OFFSET( Coverage );
     105      cnt = FT_NEXT_USHORT( p );
     106  
     107      OTV_LIMIT_CHECK( 4 * cnt );
     108      table_size = 4 + 4 * cnt;
     109  
     110      OTV_SIZE_CHECK( Coverage );
     111      otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)cnt );
     112  
     113      for ( i = 0; i < cnt; i++ )
     114      {
     115        p += 2;                                            /* Skip the value */
     116        OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     117        OTV_SIZE_CHECK( DeviceTableOffset );
     118        if ( DeviceTableOffset )
     119          otv_Device_validate( table + DeviceTableOffset, otvalid );
     120      }
     121  
     122      OTV_EXIT;
     123    }
     124  
     125  
     126    /*************************************************************************/
     127    /*************************************************************************/
     128    /*****                                                               *****/
     129    /*****                           MATH KERNING                        *****/
     130    /*****                                                               *****/
     131    /*************************************************************************/
     132    /*************************************************************************/
     133  
     134    static void
     135    otv_MathKern_validate( FT_Bytes       table,
     136                           OTV_Validator  otvalid )
     137    {
     138      FT_Bytes  p = table;
     139      FT_UInt   i, cnt, table_size;
     140  
     141      OTV_OPTIONAL_TABLE( DeviceTableOffset );
     142  
     143  
     144      /* OTV_NAME_ENTER( "MathKern" ); */
     145  
     146      OTV_LIMIT_CHECK( 2 );
     147  
     148      cnt = FT_NEXT_USHORT( p );
     149  
     150      OTV_LIMIT_CHECK( 4 * cnt + 2 );
     151      table_size = 4 + 4 * cnt;
     152  
     153      /* Heights */
     154      for ( i = 0; i < cnt; i++ )
     155      {
     156        p += 2;                                            /* Skip the value */
     157        OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     158        OTV_SIZE_CHECK( DeviceTableOffset );
     159        if ( DeviceTableOffset )
     160          otv_Device_validate( table + DeviceTableOffset, otvalid );
     161      }
     162  
     163      /* One more Kerning value */
     164      for ( i = 0; i < cnt + 1; i++ )
     165      {
     166        p += 2;                                            /* Skip the value */
     167        OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     168        OTV_SIZE_CHECK( DeviceTableOffset );
     169        if ( DeviceTableOffset )
     170          otv_Device_validate( table + DeviceTableOffset, otvalid );
     171      }
     172  
     173      OTV_EXIT;
     174    }
     175  
     176  
     177    static void
     178    otv_MathKernInfo_validate( FT_Bytes       table,
     179                               OTV_Validator  otvalid )
     180    {
     181      FT_Bytes  p = table;
     182      FT_UInt   i, j, cnt, table_size;
     183  
     184      OTV_OPTIONAL_TABLE( Coverage );
     185      OTV_OPTIONAL_TABLE( MKRecordOffset );
     186  
     187  
     188      OTV_NAME_ENTER( "MathKernInfo" );
     189  
     190      OTV_LIMIT_CHECK( 4 );
     191  
     192      OTV_OPTIONAL_OFFSET( Coverage );
     193      cnt = FT_NEXT_USHORT( p );
     194  
     195      OTV_LIMIT_CHECK( 8 * cnt );
     196      table_size = 4 + 8 * cnt;
     197  
     198      OTV_SIZE_CHECK( Coverage );
     199      otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)cnt );
     200  
     201      for ( i = 0; i < cnt; i++ )
     202      {
     203        for ( j = 0; j < 4; j++ )
     204        {
     205          OTV_OPTIONAL_OFFSET( MKRecordOffset );
     206          OTV_SIZE_CHECK( MKRecordOffset );
     207          if ( MKRecordOffset )
     208            otv_MathKern_validate( table + MKRecordOffset, otvalid );
     209        }
     210      }
     211  
     212      OTV_EXIT;
     213    }
     214  
     215  
     216    /*************************************************************************/
     217    /*************************************************************************/
     218    /*****                                                               *****/
     219    /*****                         MATH GLYPH INFO                       *****/
     220    /*****                                                               *****/
     221    /*************************************************************************/
     222    /*************************************************************************/
     223  
     224    static void
     225    otv_MathGlyphInfo_validate( FT_Bytes       table,
     226                                OTV_Validator  otvalid )
     227    {
     228      FT_Bytes  p = table;
     229      FT_UInt   MathItalicsCorrectionInfo, MathTopAccentAttachment;
     230      FT_UInt   ExtendedShapeCoverage, MathKernInfo;
     231  
     232  
     233      OTV_NAME_ENTER( "MathGlyphInfo" );
     234  
     235      OTV_LIMIT_CHECK( 8 );
     236  
     237      MathItalicsCorrectionInfo = FT_NEXT_USHORT( p );
     238      MathTopAccentAttachment   = FT_NEXT_USHORT( p );
     239      ExtendedShapeCoverage     = FT_NEXT_USHORT( p );
     240      MathKernInfo              = FT_NEXT_USHORT( p );
     241  
     242      if ( MathItalicsCorrectionInfo )
     243        otv_MathItalicsCorrectionInfo_validate(
     244          table + MathItalicsCorrectionInfo, otvalid, TRUE );
     245  
     246      /* Italic correction and Top Accent Attachment have the same format */
     247      if ( MathTopAccentAttachment )
     248        otv_MathItalicsCorrectionInfo_validate(
     249          table + MathTopAccentAttachment, otvalid, FALSE );
     250  
     251      if ( ExtendedShapeCoverage )
     252      {
     253        OTV_NAME_ENTER( "ExtendedShapeCoverage" );
     254        otv_Coverage_validate( table + ExtendedShapeCoverage, otvalid, -1 );
     255        OTV_EXIT;
     256      }
     257  
     258      if ( MathKernInfo )
     259        otv_MathKernInfo_validate( table + MathKernInfo, otvalid );
     260  
     261      OTV_EXIT;
     262    }
     263  
     264  
     265    /*************************************************************************/
     266    /*************************************************************************/
     267    /*****                                                               *****/
     268    /*****                    MATH GLYPH CONSTRUCTION                    *****/
     269    /*****                                                               *****/
     270    /*************************************************************************/
     271    /*************************************************************************/
     272  
     273    static void
     274    otv_GlyphAssembly_validate( FT_Bytes       table,
     275                                OTV_Validator  otvalid )
     276    {
     277      FT_Bytes  p = table;
     278      FT_UInt   pcnt, table_size;
     279      FT_UInt   i;
     280  
     281      OTV_OPTIONAL_TABLE( DeviceTableOffset );
     282  
     283  
     284      /* OTV_NAME_ENTER( "GlyphAssembly" ); */
     285  
     286      OTV_LIMIT_CHECK( 6 );
     287  
     288      p += 2;                           /* Skip the Italics Correction value */
     289      OTV_OPTIONAL_OFFSET( DeviceTableOffset );
     290      pcnt = FT_NEXT_USHORT( p );
     291  
     292      OTV_LIMIT_CHECK( 8 * pcnt );
     293      table_size = 6 + 8 * pcnt;
     294  
     295      OTV_SIZE_CHECK( DeviceTableOffset );
     296      if ( DeviceTableOffset )
     297        otv_Device_validate( table + DeviceTableOffset, otvalid );
     298  
     299      for ( i = 0; i < pcnt; i++ )
     300      {
     301        FT_UInt  gid;
     302  
     303  
     304        gid = FT_NEXT_USHORT( p );
     305        if ( gid >= otvalid->glyph_count )
     306          FT_INVALID_GLYPH_ID;
     307        p += 2*4;             /* skip the Start, End, Full, and Flags fields */
     308      }
     309  
     310      /* OTV_EXIT; */
     311    }
     312  
     313  
     314    static void
     315    otv_MathGlyphConstruction_validate( FT_Bytes       table,
     316                                        OTV_Validator  otvalid )
     317    {
     318      FT_Bytes  p = table;
     319      FT_UInt   vcnt, table_size;
     320      FT_UInt   i;
     321  
     322      OTV_OPTIONAL_TABLE( GlyphAssembly );
     323  
     324  
     325      /* OTV_NAME_ENTER( "MathGlyphConstruction" ); */
     326  
     327      OTV_LIMIT_CHECK( 4 );
     328  
     329      OTV_OPTIONAL_OFFSET( GlyphAssembly );
     330      vcnt = FT_NEXT_USHORT( p );
     331  
     332      OTV_LIMIT_CHECK( 4 * vcnt );
     333      table_size = 4 + 4 * vcnt;
     334  
     335      for ( i = 0; i < vcnt; i++ )
     336      {
     337        FT_UInt  gid;
     338  
     339  
     340        gid = FT_NEXT_USHORT( p );
     341        if ( gid >= otvalid->glyph_count )
     342          FT_INVALID_GLYPH_ID;
     343        p += 2;                          /* skip the size */
     344      }
     345  
     346      OTV_SIZE_CHECK( GlyphAssembly );
     347      if ( GlyphAssembly )
     348        otv_GlyphAssembly_validate( table+GlyphAssembly, otvalid );
     349  
     350      /* OTV_EXIT; */
     351    }
     352  
     353  
     354    static void
     355    otv_MathVariants_validate( FT_Bytes       table,
     356                               OTV_Validator  otvalid )
     357    {
     358      FT_Bytes  p = table;
     359      FT_UInt   vcnt, hcnt, i, table_size;
     360  
     361      OTV_OPTIONAL_TABLE( VCoverage );
     362      OTV_OPTIONAL_TABLE( HCoverage );
     363      OTV_OPTIONAL_TABLE( Offset );
     364  
     365  
     366      OTV_NAME_ENTER( "MathVariants" );
     367  
     368      OTV_LIMIT_CHECK( 10 );
     369  
     370      p += 2;                       /* Skip the MinConnectorOverlap constant */
     371      OTV_OPTIONAL_OFFSET( VCoverage );
     372      OTV_OPTIONAL_OFFSET( HCoverage );
     373      vcnt = FT_NEXT_USHORT( p );
     374      hcnt = FT_NEXT_USHORT( p );
     375  
     376      OTV_LIMIT_CHECK( 2 * vcnt + 2 * hcnt );
     377      table_size = 10 + 2 * vcnt + 2 * hcnt;
     378  
     379      OTV_SIZE_CHECK( VCoverage );
     380      if ( VCoverage )
     381        otv_Coverage_validate( table + VCoverage, otvalid, (FT_Int)vcnt );
     382  
     383      OTV_SIZE_CHECK( HCoverage );
     384      if ( HCoverage )
     385        otv_Coverage_validate( table + HCoverage, otvalid, (FT_Int)hcnt );
     386  
     387      for ( i = 0; i < vcnt; i++ )
     388      {
     389        OTV_OPTIONAL_OFFSET( Offset );
     390        OTV_SIZE_CHECK( Offset );
     391        otv_MathGlyphConstruction_validate( table + Offset, otvalid );
     392      }
     393  
     394      for ( i = 0; i < hcnt; i++ )
     395      {
     396        OTV_OPTIONAL_OFFSET( Offset );
     397        OTV_SIZE_CHECK( Offset );
     398        otv_MathGlyphConstruction_validate( table + Offset, otvalid );
     399      }
     400  
     401      OTV_EXIT;
     402    }
     403  
     404  
     405    /*************************************************************************/
     406    /*************************************************************************/
     407    /*****                                                               *****/
     408    /*****                          MATH TABLE                           *****/
     409    /*****                                                               *****/
     410    /*************************************************************************/
     411    /*************************************************************************/
     412  
     413    /* sets otvalid->glyph_count */
     414  
     415    FT_LOCAL_DEF( void )
     416    otv_MATH_validate( FT_Bytes      table,
     417                       FT_UInt       glyph_count,
     418                       FT_Validator  ftvalid )
     419    {
     420      OTV_ValidatorRec  otvalidrec;
     421      OTV_Validator     otvalid = &otvalidrec;
     422      FT_Bytes          p       = table;
     423      FT_UInt           MathConstants, MathGlyphInfo, MathVariants;
     424  
     425  
     426      otvalid->root = ftvalid;
     427  
     428      FT_TRACE3(( "validating MATH table\n" ));
     429      OTV_INIT;
     430  
     431      OTV_LIMIT_CHECK( 10 );
     432  
     433      if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
     434        FT_INVALID_FORMAT;
     435  
     436      MathConstants = FT_NEXT_USHORT( p );
     437      MathGlyphInfo = FT_NEXT_USHORT( p );
     438      MathVariants  = FT_NEXT_USHORT( p );
     439  
     440      otvalid->glyph_count = glyph_count;
     441  
     442      otv_MathConstants_validate( table + MathConstants,
     443                                  otvalid );
     444      otv_MathGlyphInfo_validate( table + MathGlyphInfo,
     445                                  otvalid );
     446      otv_MathVariants_validate ( table + MathVariants,
     447                                  otvalid );
     448  
     449      FT_TRACE4(( "\n" ));
     450    }
     451  
     452  
     453  /* END */