1 /***************************************************************************/ 2 /* */ 3 /* gxvtrak.c */ 4 /* */ 5 /* TrueTypeGX/AAT trak table validation (body). */ 6 /* */ 7 /* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 /***************************************************************************/ 19 /* */ 20 /* gxvalid is derived from both gxlayout module and otvalid module. */ 21 /* Development of gxlayout is supported by the Information-technology */ 22 /* Promotion Agency(IPA), Japan. */ 23 /* */ 24 /***************************************************************************/ 25 26 27 #include "gxvalid.h" 28 #include "gxvcommn.h" 29 30 31 /*************************************************************************/ 32 /* */ 33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 35 /* messages during execution. */ 36 /* */ 37 #undef FT_COMPONENT 38 #define FT_COMPONENT trace_gxvtrak 39 40 41 /*************************************************************************/ 42 /*************************************************************************/ 43 /***** *****/ 44 /***** Data and Types *****/ 45 /***** *****/ 46 /*************************************************************************/ 47 /*************************************************************************/ 48 49 /* 50 * referred track table format specification: 51 * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6trak.html 52 * last update was 1996. 53 * ---------------------------------------------- 54 * [MINIMUM HEADER]: GXV_TRAK_SIZE_MIN 55 * version (fixed: 32bit) = 0x00010000 56 * format (uint16: 16bit) = 0 is only defined (1996) 57 * horizOffset (uint16: 16bit) 58 * vertOffset (uint16: 16bit) 59 * reserved (uint16: 16bit) = 0 60 * ---------------------------------------------- 61 * [VARIABLE BODY]: 62 * horizData 63 * header ( 2 + 2 + 4 64 * trackTable + nTracks * ( 4 + 2 + 2 ) 65 * sizeTable + nSizes * 4 ) 66 * ---------------------------------------------- 67 * vertData 68 * header ( 2 + 2 + 4 69 * trackTable + nTracks * ( 4 + 2 + 2 ) 70 * sizeTable + nSizes * 4 ) 71 * ---------------------------------------------- 72 */ 73 typedef struct GXV_trak_DataRec_ 74 { 75 FT_UShort trackValueOffset_min; 76 FT_UShort trackValueOffset_max; 77 78 } GXV_trak_DataRec, *GXV_trak_Data; 79 80 81 #define GXV_TRAK_DATA( FIELD ) GXV_TABLE_DATA( trak, FIELD ) 82 83 84 /*************************************************************************/ 85 /*************************************************************************/ 86 /***** *****/ 87 /***** UTILITY FUNCTIONS *****/ 88 /***** *****/ 89 /*************************************************************************/ 90 /*************************************************************************/ 91 92 static void gxv_trak_trackTable_validate(FT_Bytes table,FT_Bytes limit,FT_UShort nTracks,GXV_Validator valid)93 gxv_trak_trackTable_validate( FT_Bytes table, 94 FT_Bytes limit, 95 FT_UShort nTracks, 96 GXV_Validator valid ) 97 { 98 FT_Bytes p = table; 99 100 FT_Fixed track, t; 101 FT_UShort nameIndex; 102 FT_UShort offset; 103 FT_UShort i, j; 104 105 106 GXV_NAME_ENTER( "trackTable" ); 107 108 GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFFU; 109 GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000; 110 111 GXV_LIMIT_CHECK( nTracks * ( 4 + 2 + 2 ) ); 112 113 for ( i = 0; i < nTracks; i ++ ) 114 { 115 p = table + i * ( 4 + 2 + 2 ); 116 track = FT_NEXT_LONG( p ); 117 nameIndex = FT_NEXT_USHORT( p ); 118 offset = FT_NEXT_USHORT( p ); 119 120 if ( offset < GXV_TRAK_DATA( trackValueOffset_min ) ) 121 GXV_TRAK_DATA( trackValueOffset_min ) = offset; 122 if ( offset > GXV_TRAK_DATA( trackValueOffset_max ) ) 123 GXV_TRAK_DATA( trackValueOffset_max ) = offset; 124 125 gxv_sfntName_validate( nameIndex, 256, 32767, valid ); 126 127 for ( j = i; j < nTracks; j ++ ) 128 { 129 p = table + j * ( 4 + 2 + 2 ); 130 t = FT_NEXT_LONG( p ); 131 if ( t == track ) 132 GXV_TRACE(( "duplicated entries found for track value 0x%x\n", 133 track )); 134 } 135 } 136 137 valid->subtable_length = p - table; 138 GXV_EXIT; 139 } 140 141 142 static void gxv_trak_trackData_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator valid)143 gxv_trak_trackData_validate( FT_Bytes table, 144 FT_Bytes limit, 145 GXV_Validator valid ) 146 { 147 FT_Bytes p = table; 148 FT_UShort nTracks; 149 FT_UShort nSizes; 150 FT_ULong sizeTableOffset; 151 152 GXV_ODTECT( 4, odtect ); 153 154 155 GXV_ODTECT_INIT( odtect ); 156 GXV_NAME_ENTER( "trackData" ); 157 158 /* read the header of trackData */ 159 GXV_LIMIT_CHECK( 2 + 2 + 4 ); 160 nTracks = FT_NEXT_USHORT( p ); 161 nSizes = FT_NEXT_USHORT( p ); 162 sizeTableOffset = FT_NEXT_ULONG( p ); 163 164 gxv_odtect_add_range( table, p - table, "trackData header", odtect ); 165 166 /* validate trackTable */ 167 gxv_trak_trackTable_validate( p, limit, nTracks, valid ); 168 gxv_odtect_add_range( p, valid->subtable_length, 169 "trackTable", odtect ); 170 171 /* sizeTable is array of FT_Fixed, don't check contents */ 172 p = valid->root->base + sizeTableOffset; 173 GXV_LIMIT_CHECK( nSizes * 4 ); 174 gxv_odtect_add_range( p, nSizes * 4, "sizeTable", odtect ); 175 176 /* validate trackValueOffet */ 177 p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_min ); 178 if ( limit - p < nTracks * nSizes * 2 ) 179 GXV_TRACE(( "too short trackValue array\n" )); 180 181 p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_max ); 182 GXV_LIMIT_CHECK( nSizes * 2 ); 183 184 gxv_odtect_add_range( valid->root->base 185 + GXV_TRAK_DATA( trackValueOffset_min ), 186 GXV_TRAK_DATA( trackValueOffset_max ) 187 - GXV_TRAK_DATA( trackValueOffset_min ) 188 + nSizes * 2, 189 "trackValue array", odtect ); 190 191 gxv_odtect_validate( odtect, valid ); 192 193 GXV_EXIT; 194 } 195 196 197 /*************************************************************************/ 198 /*************************************************************************/ 199 /***** *****/ 200 /***** trak TABLE *****/ 201 /***** *****/ 202 /*************************************************************************/ 203 /*************************************************************************/ 204 205 FT_LOCAL_DEF( void ) gxv_trak_validate(FT_Bytes table,FT_Face face,FT_Validator ftvalid)206 gxv_trak_validate( FT_Bytes table, 207 FT_Face face, 208 FT_Validator ftvalid ) 209 { 210 FT_Bytes p = table; 211 FT_Bytes limit = 0; 212 213 GXV_ValidatorRec validrec; 214 GXV_Validator valid = &validrec; 215 GXV_trak_DataRec trakrec; 216 GXV_trak_Data trak = &trakrec; 217 218 FT_ULong version; 219 FT_UShort format; 220 FT_UShort horizOffset; 221 FT_UShort vertOffset; 222 FT_UShort reserved; 223 224 225 GXV_ODTECT( 3, odtect ); 226 227 GXV_ODTECT_INIT( odtect ); 228 valid->root = ftvalid; 229 valid->table_data = trak; 230 valid->face = face; 231 232 limit = valid->root->limit; 233 234 FT_TRACE3(( "validating `trak' table\n" )); 235 GXV_INIT; 236 237 GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 + 2 ); 238 version = FT_NEXT_ULONG( p ); 239 format = FT_NEXT_USHORT( p ); 240 horizOffset = FT_NEXT_USHORT( p ); 241 vertOffset = FT_NEXT_USHORT( p ); 242 reserved = FT_NEXT_USHORT( p ); 243 244 GXV_TRACE(( " (version = 0x%08x)\n", version )); 245 GXV_TRACE(( " (format = 0x%04x)\n", format )); 246 GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset )); 247 GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset )); 248 GXV_TRACE(( " (reserved = 0x%04x)\n", reserved )); 249 250 /* Version 1.0 (always:1996) */ 251 if ( version != 0x00010000UL ) 252 FT_INVALID_FORMAT; 253 254 /* format 0 (always:1996) */ 255 if ( format != 0x0000 ) 256 FT_INVALID_FORMAT; 257 258 GXV_32BIT_ALIGNMENT_VALIDATE( horizOffset ); 259 GXV_32BIT_ALIGNMENT_VALIDATE( vertOffset ); 260 261 /* Reserved Fixed Value (always) */ 262 if ( reserved != 0x0000 ) 263 FT_INVALID_DATA; 264 265 /* validate trackData */ 266 if ( 0 < horizOffset ) 267 { 268 gxv_trak_trackData_validate( table + horizOffset, limit, valid ); 269 gxv_odtect_add_range( table + horizOffset, valid->subtable_length, 270 "horizJustData", odtect ); 271 } 272 273 if ( 0 < vertOffset ) 274 { 275 gxv_trak_trackData_validate( table + vertOffset, limit, valid ); 276 gxv_odtect_add_range( table + vertOffset, valid->subtable_length, 277 "vertJustData", odtect ); 278 } 279 280 gxv_odtect_validate( odtect, valid ); 281 282 FT_TRACE4(( "\n" )); 283 } 284 285 286 /* END */ 287