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