• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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