1 /**************************************************************************** 2 * 3 * gxvtrak.c 4 * 5 * TrueTypeGX/AAT trak table validation (body). 6 * 7 * Copyright (C) 2004-2020 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 gxv_trak_trackTable_validate(FT_Bytes table,FT_Bytes limit,FT_UShort nTracks,GXV_Validator gxvalid)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%x\n", 134 track )); 135 } 136 } 137 138 gxvalid->subtable_length = (FT_ULong)( p - table ); 139 GXV_EXIT; 140 } 141 142 143 static void gxv_trak_trackData_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator gxvalid)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 ) gxv_trak_validate(FT_Bytes table,FT_Face face,FT_Validator ftvalid)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%08x)\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 */ 289