Home | History | Annotate | Download | only in otvalid
      1 /****************************************************************************
      2  *
      3  * otvmath.c
      4  *
      5  *   OpenType MATH table validation (body).
      6  *
      7  * Copyright 2007-2018 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  trace_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 */
    454