1 /****************************************************************************
2  *
3  * otvgdef.c
4  *
5  *   OpenType GDEF table validation (body).
6  *
7  * Copyright (C) 2004-2020 by
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 #include "otvalid.h"
20 #include "otvcommn.h"
21 
22 
23   /**************************************************************************
24    *
25    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
26    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
27    * messages during execution.
28    */
29 #undef  FT_COMPONENT
30 #define FT_COMPONENT  otvgdef
31 
32 
33   /*************************************************************************/
34   /*************************************************************************/
35   /*****                                                               *****/
36   /*****                      UTILITY FUNCTIONS                        *****/
37   /*****                                                               *****/
38   /*************************************************************************/
39   /*************************************************************************/
40 
41 #define AttachListFunc    otv_O_x_Ox
42 #define LigCaretListFunc  otv_O_x_Ox
43 
44   /* sets valid->extra1 (0)           */
45 
46   static void
otv_O_x_Ox(FT_Bytes table,OTV_Validator otvalid)47   otv_O_x_Ox( FT_Bytes       table,
48               OTV_Validator  otvalid )
49   {
50     FT_Bytes           p = table;
51     FT_Bytes           Coverage;
52     FT_UInt            GlyphCount;
53     OTV_Validate_Func  func;
54 
55 
56     OTV_ENTER;
57 
58     OTV_LIMIT_CHECK( 4 );
59     Coverage   = table + FT_NEXT_USHORT( p );
60     GlyphCount = FT_NEXT_USHORT( p );
61 
62     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
63 
64     otv_Coverage_validate( Coverage, otvalid, (FT_Int)GlyphCount );
65     if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
66       FT_INVALID_DATA;
67 
68     OTV_LIMIT_CHECK( GlyphCount * 2 );
69 
70     otvalid->nesting_level++;
71     func            = otvalid->func[otvalid->nesting_level];
72     otvalid->extra1 = 0;
73 
74     for ( ; GlyphCount > 0; GlyphCount-- )
75       func( table + FT_NEXT_USHORT( p ), otvalid );
76 
77     otvalid->nesting_level--;
78 
79     OTV_EXIT;
80   }
81 
82 
83   /*************************************************************************/
84   /*************************************************************************/
85   /*****                                                               *****/
86   /*****                       LIGATURE CARETS                         *****/
87   /*****                                                               *****/
88   /*************************************************************************/
89   /*************************************************************************/
90 
91 #define CaretValueFunc  otv_CaretValue_validate
92 
93   static void
otv_CaretValue_validate(FT_Bytes table,OTV_Validator otvalid)94   otv_CaretValue_validate( FT_Bytes       table,
95                            OTV_Validator  otvalid )
96   {
97     FT_Bytes  p = table;
98     FT_UInt   CaretValueFormat;
99 
100 
101     OTV_ENTER;
102 
103     OTV_LIMIT_CHECK( 4 );
104 
105     CaretValueFormat = FT_NEXT_USHORT( p );
106 
107     OTV_TRACE(( " (format = %d)\n", CaretValueFormat ));
108 
109     switch ( CaretValueFormat )
110     {
111     case 1:     /* CaretValueFormat1 */
112       /* skip Coordinate, no test */
113       break;
114 
115     case 2:     /* CaretValueFormat2 */
116       /* skip CaretValuePoint, no test */
117       break;
118 
119     case 3:     /* CaretValueFormat3 */
120       p += 2;   /* skip Coordinate */
121 
122       OTV_LIMIT_CHECK( 2 );
123 
124       /* DeviceTable */
125       otv_Device_validate( table + FT_NEXT_USHORT( p ), otvalid );
126       break;
127 
128     default:
129       FT_INVALID_FORMAT;
130     }
131 
132     OTV_EXIT;
133   }
134 
135 
136   /*************************************************************************/
137   /*************************************************************************/
138   /*****                                                               *****/
139   /*****                       MARK GLYPH SETS                         *****/
140   /*****                                                               *****/
141   /*************************************************************************/
142   /*************************************************************************/
143 
144   static void
otv_MarkGlyphSets_validate(FT_Bytes table,OTV_Validator otvalid)145   otv_MarkGlyphSets_validate( FT_Bytes       table,
146                               OTV_Validator  otvalid )
147   {
148     FT_Bytes  p = table;
149     FT_UInt   MarkGlyphSetCount;
150 
151 
152     OTV_NAME_ENTER( "MarkGlyphSets" );
153 
154     p += 2;     /* skip Format */
155 
156     OTV_LIMIT_CHECK( 2 );
157     MarkGlyphSetCount = FT_NEXT_USHORT( p );
158 
159     OTV_TRACE(( " (MarkGlyphSetCount = %d)\n", MarkGlyphSetCount ));
160 
161     OTV_LIMIT_CHECK( MarkGlyphSetCount * 4 );      /* CoverageOffsets */
162 
163     for ( ; MarkGlyphSetCount > 0; MarkGlyphSetCount-- )
164       otv_Coverage_validate( table + FT_NEXT_ULONG( p ), otvalid, -1 );
165 
166     OTV_EXIT;
167   }
168 
169 
170   /*************************************************************************/
171   /*************************************************************************/
172   /*****                                                               *****/
173   /*****                         GDEF TABLE                            *****/
174   /*****                                                               *****/
175   /*************************************************************************/
176   /*************************************************************************/
177 
178   /* sets otvalid->glyph_count */
179 
180   FT_LOCAL_DEF( void )
otv_GDEF_validate(FT_Bytes table,FT_Bytes gsub,FT_Bytes gpos,FT_UInt glyph_count,FT_Validator ftvalid)181   otv_GDEF_validate( FT_Bytes      table,
182                      FT_Bytes      gsub,
183                      FT_Bytes      gpos,
184                      FT_UInt       glyph_count,
185                      FT_Validator  ftvalid )
186   {
187     OTV_ValidatorRec  otvalidrec;
188     OTV_Validator     otvalid = &otvalidrec;
189     FT_Bytes          p       = table;
190     FT_UInt           table_size;
191     FT_UShort         version;
192     FT_Bool           need_MarkAttachClassDef = 1;
193 
194     OTV_OPTIONAL_TABLE( GlyphClassDef );
195     OTV_OPTIONAL_TABLE( AttachListOffset );
196     OTV_OPTIONAL_TABLE( LigCaretListOffset );
197     OTV_OPTIONAL_TABLE( MarkAttachClassDef );
198     OTV_OPTIONAL_TABLE( MarkGlyphSetsDef );
199 
200     OTV_OPTIONAL_TABLE32( itemVarStore );
201 
202 
203     otvalid->root = ftvalid;
204 
205     FT_TRACE3(( "validating GDEF table\n" ));
206     OTV_INIT;
207 
208     OTV_LIMIT_CHECK( 4 );
209 
210     if ( FT_NEXT_USHORT( p ) != 1 )  /* majorVersion */
211       FT_INVALID_FORMAT;
212 
213     version = FT_NEXT_USHORT( p );   /* minorVersion */
214 
215     table_size = 10;
216     switch ( version )
217     {
218     case 0:
219       /* MarkAttachClassDef has been added to the OpenType */
220       /* specification without increasing GDEF's version,  */
221       /* so we use this ugly hack to find out whether the  */
222       /* table is needed actually.                         */
223 
224       need_MarkAttachClassDef = FT_BOOL(
225         otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) ||
226         otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) );
227 
228       if ( need_MarkAttachClassDef )
229       {
230         OTV_LIMIT_CHECK( 8 );
231         table_size += 2;
232       }
233       else
234         OTV_LIMIT_CHECK( 6 );  /* OpenType < 1.2 */
235 
236       break;
237 
238     case 2:
239       OTV_LIMIT_CHECK( 10 );
240       table_size += 4;
241       break;
242 
243     case 3:
244       OTV_LIMIT_CHECK( 14 );
245       table_size += 8;
246       break;
247 
248     default:
249       FT_INVALID_FORMAT;
250     }
251 
252     otvalid->glyph_count = glyph_count;
253 
254     OTV_OPTIONAL_OFFSET( GlyphClassDef );
255     OTV_SIZE_CHECK( GlyphClassDef );
256     if ( GlyphClassDef )
257       otv_ClassDef_validate( table + GlyphClassDef, otvalid );
258 
259     OTV_OPTIONAL_OFFSET( AttachListOffset );
260     OTV_SIZE_CHECK( AttachListOffset );
261     if ( AttachListOffset )
262     {
263       OTV_NEST2( AttachList, AttachPoint );
264       OTV_RUN( table + AttachListOffset, otvalid );
265     }
266 
267     OTV_OPTIONAL_OFFSET( LigCaretListOffset );
268     OTV_SIZE_CHECK( LigCaretListOffset );
269     if ( LigCaretListOffset )
270     {
271       OTV_NEST3( LigCaretList, LigGlyph, CaretValue );
272       OTV_RUN( table + LigCaretListOffset, otvalid );
273     }
274 
275     if ( need_MarkAttachClassDef )
276     {
277       OTV_OPTIONAL_OFFSET( MarkAttachClassDef );
278       OTV_SIZE_CHECK( MarkAttachClassDef );
279       if ( MarkAttachClassDef )
280         otv_ClassDef_validate( table + MarkAttachClassDef, otvalid );
281     }
282 
283     if ( version > 0 )
284     {
285       OTV_OPTIONAL_OFFSET( MarkGlyphSetsDef );
286       OTV_SIZE_CHECK( MarkGlyphSetsDef );
287       if ( MarkGlyphSetsDef )
288         otv_MarkGlyphSets_validate( table + MarkGlyphSetsDef, otvalid );
289     }
290 
291     if ( version > 2 )
292     {
293       OTV_OPTIONAL_OFFSET32( itemVarStore );
294       OTV_SIZE_CHECK32( itemVarStore );
295       if ( itemVarStore )
296         OTV_TRACE(( "  [omitting itemVarStore validation]\n" )); /* XXX */
297     }
298 
299     FT_TRACE4(( "\n" ));
300   }
301 
302 
303 /* END */
304