1 /****************************************************************************
2  *
3  * otvcommn.c
4  *
5  *   OpenType common tables validation (body).
6  *
7  * Copyright (C) 2004-2019 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 "otvcommn.h"
20 
21 
22   /**************************************************************************
23    *
24    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
25    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
26    * messages during execution.
27    */
28 #undef  FT_COMPONENT
29 #define FT_COMPONENT  otvcommon
30 
31 
32   /*************************************************************************/
33   /*************************************************************************/
34   /*****                                                               *****/
35   /*****                       COVERAGE TABLE                          *****/
36   /*****                                                               *****/
37   /*************************************************************************/
38   /*************************************************************************/
39 
40   FT_LOCAL_DEF( void )
otv_Coverage_validate(FT_Bytes table,OTV_Validator otvalid,FT_Int expected_count)41   otv_Coverage_validate( FT_Bytes       table,
42                          OTV_Validator  otvalid,
43                          FT_Int         expected_count )
44   {
45     FT_Bytes  p = table;
46     FT_UInt   CoverageFormat;
47     FT_UInt   total = 0;
48 
49 
50     OTV_NAME_ENTER( "Coverage" );
51 
52     OTV_LIMIT_CHECK( 4 );
53     CoverageFormat = FT_NEXT_USHORT( p );
54 
55     OTV_TRACE(( " (format %d)\n", CoverageFormat ));
56 
57     switch ( CoverageFormat )
58     {
59     case 1:     /* CoverageFormat1 */
60       {
61         FT_UInt  GlyphCount;
62         FT_UInt  i;
63 
64 
65         GlyphCount = FT_NEXT_USHORT( p );
66 
67         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
68 
69         OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */
70 
71         for ( i = 0; i < GlyphCount; i++ )
72         {
73           FT_UInt  gid;
74 
75 
76           gid = FT_NEXT_USHORT( p );
77           if ( gid >= otvalid->glyph_count )
78             FT_INVALID_GLYPH_ID;
79         }
80 
81         total = GlyphCount;
82       }
83       break;
84 
85     case 2:     /* CoverageFormat2 */
86       {
87         FT_UInt  n, RangeCount;
88         FT_UInt  Start, End, StartCoverageIndex, last = 0;
89 
90 
91         RangeCount = FT_NEXT_USHORT( p );
92 
93         OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
94 
95         OTV_LIMIT_CHECK( RangeCount * 6 );
96 
97         /* RangeRecord */
98         for ( n = 0; n < RangeCount; n++ )
99         {
100           Start              = FT_NEXT_USHORT( p );
101           End                = FT_NEXT_USHORT( p );
102           StartCoverageIndex = FT_NEXT_USHORT( p );
103 
104           if ( Start > End || StartCoverageIndex != total )
105             FT_INVALID_DATA;
106 
107           if ( End >= otvalid->glyph_count )
108             FT_INVALID_GLYPH_ID;
109 
110           if ( n > 0 && Start <= last )
111             FT_INVALID_DATA;
112 
113           total += End - Start + 1;
114           last   = End;
115         }
116       }
117       break;
118 
119     default:
120       FT_INVALID_FORMAT;
121     }
122 
123     /* Generally, a coverage table offset has an associated count field.  */
124     /* The number of glyphs in the table should match this field.  If     */
125     /* there is no associated count, a value of -1 tells us not to check. */
126     if ( expected_count != -1 && (FT_UInt)expected_count != total )
127       FT_INVALID_DATA;
128 
129     OTV_EXIT;
130   }
131 
132 
133   FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_first(FT_Bytes table)134   otv_Coverage_get_first( FT_Bytes  table )
135   {
136     FT_Bytes  p = table;
137 
138 
139     p += 4;     /* skip CoverageFormat and Glyph/RangeCount */
140 
141     return FT_NEXT_USHORT( p );
142   }
143 
144 
145   FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_last(FT_Bytes table)146   otv_Coverage_get_last( FT_Bytes  table )
147   {
148     FT_Bytes  p = table;
149     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
150     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
151     FT_UInt   result = 0;
152 
153 
154     switch ( CoverageFormat )
155     {
156     case 1:
157       p += ( count - 1 ) * 2;
158       result = FT_NEXT_USHORT( p );
159       break;
160 
161     case 2:
162       p += ( count - 1 ) * 6 + 2;
163       result = FT_NEXT_USHORT( p );
164       break;
165 
166     default:
167       ;
168     }
169 
170     return result;
171   }
172 
173 
174   FT_LOCAL_DEF( FT_UInt )
otv_Coverage_get_count(FT_Bytes table)175   otv_Coverage_get_count( FT_Bytes  table )
176   {
177     FT_Bytes  p              = table;
178     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
179     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
180     FT_UInt   result         = 0;
181 
182 
183     switch ( CoverageFormat )
184     {
185     case 1:
186       return count;
187 
188     case 2:
189       {
190         FT_UInt  Start, End;
191 
192 
193         for ( ; count > 0; count-- )
194         {
195           Start = FT_NEXT_USHORT( p );
196           End   = FT_NEXT_USHORT( p );
197           p    += 2;                    /* skip StartCoverageIndex */
198 
199           result += End - Start + 1;
200         }
201       }
202       break;
203 
204     default:
205       ;
206     }
207 
208     return result;
209   }
210 
211 
212   /*************************************************************************/
213   /*************************************************************************/
214   /*****                                                               *****/
215   /*****                   CLASS DEFINITION TABLE                      *****/
216   /*****                                                               *****/
217   /*************************************************************************/
218   /*************************************************************************/
219 
220   FT_LOCAL_DEF( void )
otv_ClassDef_validate(FT_Bytes table,OTV_Validator otvalid)221   otv_ClassDef_validate( FT_Bytes       table,
222                          OTV_Validator  otvalid )
223   {
224     FT_Bytes  p = table;
225     FT_UInt   ClassFormat;
226 
227 
228     OTV_NAME_ENTER( "ClassDef" );
229 
230     OTV_LIMIT_CHECK( 4 );
231     ClassFormat = FT_NEXT_USHORT( p );
232 
233     OTV_TRACE(( " (format %d)\n", ClassFormat ));
234 
235     switch ( ClassFormat )
236     {
237     case 1:     /* ClassDefFormat1 */
238       {
239         FT_UInt  StartGlyph;
240         FT_UInt  GlyphCount;
241 
242 
243         OTV_LIMIT_CHECK( 4 );
244 
245         StartGlyph = FT_NEXT_USHORT( p );
246         GlyphCount = FT_NEXT_USHORT( p );
247 
248         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
249 
250         OTV_LIMIT_CHECK( GlyphCount * 2 );    /* ClassValueArray */
251 
252         if ( StartGlyph + GlyphCount - 1 >= otvalid->glyph_count )
253           FT_INVALID_GLYPH_ID;
254       }
255       break;
256 
257     case 2:     /* ClassDefFormat2 */
258       {
259         FT_UInt  n, ClassRangeCount;
260         FT_UInt  Start, End, last = 0;
261 
262 
263         ClassRangeCount = FT_NEXT_USHORT( p );
264 
265         OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
266 
267         OTV_LIMIT_CHECK( ClassRangeCount * 6 );
268 
269         /* ClassRangeRecord */
270         for ( n = 0; n < ClassRangeCount; n++ )
271         {
272           Start = FT_NEXT_USHORT( p );
273           End   = FT_NEXT_USHORT( p );
274           p    += 2;                        /* skip Class */
275 
276           if ( Start > End || ( n > 0 && Start <= last ) )
277             FT_INVALID_DATA;
278 
279           if ( End >= otvalid->glyph_count )
280             FT_INVALID_GLYPH_ID;
281 
282           last = End;
283         }
284       }
285       break;
286 
287     default:
288       FT_INVALID_FORMAT;
289     }
290 
291     /* no need to check glyph indices used as input to class definition   */
292     /* tables since even invalid glyph indices return a meaningful result */
293 
294     OTV_EXIT;
295   }
296 
297 
298   /*************************************************************************/
299   /*************************************************************************/
300   /*****                                                               *****/
301   /*****                      DEVICE TABLE                             *****/
302   /*****                                                               *****/
303   /*************************************************************************/
304   /*************************************************************************/
305 
306   FT_LOCAL_DEF( void )
otv_Device_validate(FT_Bytes table,OTV_Validator otvalid)307   otv_Device_validate( FT_Bytes       table,
308                        OTV_Validator  otvalid )
309   {
310     FT_Bytes  p = table;
311     FT_UInt   StartSize, EndSize, DeltaFormat, count;
312 
313 
314     OTV_NAME_ENTER( "Device" );
315 
316     OTV_LIMIT_CHECK( 6 );
317     StartSize   = FT_NEXT_USHORT( p );
318     EndSize     = FT_NEXT_USHORT( p );
319     DeltaFormat = FT_NEXT_USHORT( p );
320 
321     if ( DeltaFormat == 0x8000U )
322     {
323       /* VariationIndex, nothing to do */
324     }
325     else
326     {
327       if ( DeltaFormat < 1 || DeltaFormat > 3 )
328         FT_INVALID_FORMAT;
329 
330       if ( EndSize < StartSize )
331         FT_INVALID_DATA;
332 
333       count = EndSize - StartSize + 1;
334       OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
335     }
336 
337     OTV_EXIT;
338   }
339 
340 
341   /*************************************************************************/
342   /*************************************************************************/
343   /*****                                                               *****/
344   /*****                         LOOKUPS                               *****/
345   /*****                                                               *****/
346   /*************************************************************************/
347   /*************************************************************************/
348 
349   /* uses otvalid->type_count */
350   /* uses otvalid->type_funcs */
351 
352   FT_LOCAL_DEF( void )
otv_Lookup_validate(FT_Bytes table,OTV_Validator otvalid)353   otv_Lookup_validate( FT_Bytes       table,
354                        OTV_Validator  otvalid )
355   {
356     FT_Bytes           p = table;
357     FT_UInt            LookupType, LookupFlag, SubTableCount;
358     OTV_Validate_Func  validate;
359 
360 
361     OTV_NAME_ENTER( "Lookup" );
362 
363     OTV_LIMIT_CHECK( 6 );
364     LookupType    = FT_NEXT_USHORT( p );
365     LookupFlag    = FT_NEXT_USHORT( p );
366     SubTableCount = FT_NEXT_USHORT( p );
367 
368     OTV_TRACE(( " (type %d)\n", LookupType ));
369 
370     if ( LookupType == 0 || LookupType > otvalid->type_count )
371       FT_INVALID_DATA;
372 
373     validate = otvalid->type_funcs[LookupType - 1];
374 
375     OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
376 
377     OTV_LIMIT_CHECK( SubTableCount * 2 );
378 
379     /* SubTable */
380     for ( ; SubTableCount > 0; SubTableCount-- )
381       validate( table + FT_NEXT_USHORT( p ), otvalid );
382 
383     if ( LookupFlag & 0x10 )
384       OTV_LIMIT_CHECK( 2 );  /* MarkFilteringSet */
385 
386     OTV_EXIT;
387   }
388 
389 
390   /* uses valid->lookup_count */
391 
392   FT_LOCAL_DEF( void )
otv_LookupList_validate(FT_Bytes table,OTV_Validator otvalid)393   otv_LookupList_validate( FT_Bytes       table,
394                            OTV_Validator  otvalid )
395   {
396     FT_Bytes  p = table;
397     FT_UInt   LookupCount;
398 
399 
400     OTV_NAME_ENTER( "LookupList" );
401 
402     OTV_LIMIT_CHECK( 2 );
403     LookupCount = FT_NEXT_USHORT( p );
404 
405     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
406 
407     OTV_LIMIT_CHECK( LookupCount * 2 );
408 
409     otvalid->lookup_count = LookupCount;
410 
411     /* Lookup */
412     for ( ; LookupCount > 0; LookupCount-- )
413       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), otvalid );
414 
415     OTV_EXIT;
416   }
417 
418 
419   static FT_UInt
otv_LookupList_get_count(FT_Bytes table)420   otv_LookupList_get_count( FT_Bytes  table )
421   {
422     return FT_NEXT_USHORT( table );
423   }
424 
425 
426   /*************************************************************************/
427   /*************************************************************************/
428   /*****                                                               *****/
429   /*****                        FEATURES                               *****/
430   /*****                                                               *****/
431   /*************************************************************************/
432   /*************************************************************************/
433 
434   /* uses otvalid->lookup_count */
435 
436   FT_LOCAL_DEF( void )
otv_Feature_validate(FT_Bytes table,OTV_Validator otvalid)437   otv_Feature_validate( FT_Bytes       table,
438                         OTV_Validator  otvalid )
439   {
440     FT_Bytes  p = table;
441     FT_UInt   LookupCount;
442 
443 
444     OTV_NAME_ENTER( "Feature" );
445 
446     OTV_LIMIT_CHECK( 4 );
447     p           += 2;                   /* skip FeatureParams (unused) */
448     LookupCount  = FT_NEXT_USHORT( p );
449 
450     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
451 
452     OTV_LIMIT_CHECK( LookupCount * 2 );
453 
454     /* LookupListIndex */
455     for ( ; LookupCount > 0; LookupCount-- )
456       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
457         FT_INVALID_DATA;
458 
459     OTV_EXIT;
460   }
461 
462 
463   static FT_UInt
otv_Feature_get_count(FT_Bytes table)464   otv_Feature_get_count( FT_Bytes  table )
465   {
466     return FT_NEXT_USHORT( table );
467   }
468 
469 
470   /* sets otvalid->lookup_count */
471 
472   FT_LOCAL_DEF( void )
otv_FeatureList_validate(FT_Bytes table,FT_Bytes lookups,OTV_Validator otvalid)473   otv_FeatureList_validate( FT_Bytes       table,
474                             FT_Bytes       lookups,
475                             OTV_Validator  otvalid )
476   {
477     FT_Bytes  p = table;
478     FT_UInt   FeatureCount;
479 
480 
481     OTV_NAME_ENTER( "FeatureList" );
482 
483     OTV_LIMIT_CHECK( 2 );
484     FeatureCount = FT_NEXT_USHORT( p );
485 
486     OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
487 
488     OTV_LIMIT_CHECK( FeatureCount * 2 );
489 
490     otvalid->lookup_count = otv_LookupList_get_count( lookups );
491 
492     /* FeatureRecord */
493     for ( ; FeatureCount > 0; FeatureCount-- )
494     {
495       p += 4;       /* skip FeatureTag */
496 
497       /* Feature */
498       otv_Feature_validate( table + FT_NEXT_USHORT( p ), otvalid );
499     }
500 
501     OTV_EXIT;
502   }
503 
504 
505   /*************************************************************************/
506   /*************************************************************************/
507   /*****                                                               *****/
508   /*****                       LANGUAGE SYSTEM                         *****/
509   /*****                                                               *****/
510   /*************************************************************************/
511   /*************************************************************************/
512 
513 
514   /* uses otvalid->extra1 (number of features) */
515 
516   FT_LOCAL_DEF( void )
otv_LangSys_validate(FT_Bytes table,OTV_Validator otvalid)517   otv_LangSys_validate( FT_Bytes       table,
518                         OTV_Validator  otvalid )
519   {
520     FT_Bytes  p = table;
521     FT_UInt   ReqFeatureIndex;
522     FT_UInt   FeatureCount;
523 
524 
525     OTV_NAME_ENTER( "LangSys" );
526 
527     OTV_LIMIT_CHECK( 6 );
528     p              += 2;                    /* skip LookupOrder (unused) */
529     ReqFeatureIndex = FT_NEXT_USHORT( p );
530     FeatureCount    = FT_NEXT_USHORT( p );
531 
532     OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
533     OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
534 
535     if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= otvalid->extra1 )
536       FT_INVALID_DATA;
537 
538     OTV_LIMIT_CHECK( FeatureCount * 2 );
539 
540     /* FeatureIndex */
541     for ( ; FeatureCount > 0; FeatureCount-- )
542       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
543         FT_INVALID_DATA;
544 
545     OTV_EXIT;
546   }
547 
548 
549   /*************************************************************************/
550   /*************************************************************************/
551   /*****                                                               *****/
552   /*****                           SCRIPTS                             *****/
553   /*****                                                               *****/
554   /*************************************************************************/
555   /*************************************************************************/
556 
557   FT_LOCAL_DEF( void )
otv_Script_validate(FT_Bytes table,OTV_Validator otvalid)558   otv_Script_validate( FT_Bytes       table,
559                        OTV_Validator  otvalid )
560   {
561     FT_UInt   DefaultLangSys, LangSysCount;
562     FT_Bytes  p = table;
563 
564 
565     OTV_NAME_ENTER( "Script" );
566 
567     OTV_LIMIT_CHECK( 4 );
568     DefaultLangSys = FT_NEXT_USHORT( p );
569     LangSysCount   = FT_NEXT_USHORT( p );
570 
571     OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
572 
573     if ( DefaultLangSys != 0 )
574       otv_LangSys_validate( table + DefaultLangSys, otvalid );
575 
576     OTV_LIMIT_CHECK( LangSysCount * 6 );
577 
578     /* LangSysRecord */
579     for ( ; LangSysCount > 0; LangSysCount-- )
580     {
581       p += 4;       /* skip LangSysTag */
582 
583       /* LangSys */
584       otv_LangSys_validate( table + FT_NEXT_USHORT( p ), otvalid );
585     }
586 
587     OTV_EXIT;
588   }
589 
590 
591   /* sets otvalid->extra1 (number of features) */
592 
593   FT_LOCAL_DEF( void )
otv_ScriptList_validate(FT_Bytes table,FT_Bytes features,OTV_Validator otvalid)594   otv_ScriptList_validate( FT_Bytes       table,
595                            FT_Bytes       features,
596                            OTV_Validator  otvalid )
597   {
598     FT_UInt   ScriptCount;
599     FT_Bytes  p = table;
600 
601 
602     OTV_NAME_ENTER( "ScriptList" );
603 
604     OTV_LIMIT_CHECK( 2 );
605     ScriptCount = FT_NEXT_USHORT( p );
606 
607     OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
608 
609     OTV_LIMIT_CHECK( ScriptCount * 6 );
610 
611     otvalid->extra1 = otv_Feature_get_count( features );
612 
613     /* ScriptRecord */
614     for ( ; ScriptCount > 0; ScriptCount-- )
615     {
616       p += 4;       /* skip ScriptTag */
617 
618       otv_Script_validate( table + FT_NEXT_USHORT( p ), otvalid ); /* Script */
619     }
620 
621     OTV_EXIT;
622   }
623 
624 
625   /*************************************************************************/
626   /*************************************************************************/
627   /*****                                                               *****/
628   /*****                      UTILITY FUNCTIONS                        *****/
629   /*****                                                               *****/
630   /*************************************************************************/
631   /*************************************************************************/
632 
633   /*
634      u:   uint16
635      ux:  unit16 [x]
636 
637      s:   struct
638      sx:  struct [x]
639      sxy: struct [x], using external y count
640 
641      x:   uint16 x
642 
643      C:   Coverage
644 
645      O:   Offset
646      On:  Offset (NULL)
647      Ox:  Offset [x]
648      Onx: Offset (NULL) [x]
649   */
650 
651   FT_LOCAL_DEF( void )
otv_x_Ox(FT_Bytes table,OTV_Validator otvalid)652   otv_x_Ox( FT_Bytes       table,
653             OTV_Validator  otvalid )
654   {
655     FT_Bytes           p = table;
656     FT_UInt            Count;
657     OTV_Validate_Func  func;
658 
659 
660     OTV_ENTER;
661 
662     OTV_LIMIT_CHECK( 2 );
663     Count = FT_NEXT_USHORT( p );
664 
665     OTV_TRACE(( " (Count = %d)\n", Count ));
666 
667     OTV_LIMIT_CHECK( Count * 2 );
668 
669     otvalid->nesting_level++;
670     func = otvalid->func[otvalid->nesting_level];
671 
672     for ( ; Count > 0; Count-- )
673       func( table + FT_NEXT_USHORT( p ), otvalid );
674 
675     otvalid->nesting_level--;
676 
677     OTV_EXIT;
678   }
679 
680 
681   FT_LOCAL_DEF( void )
otv_u_C_x_Ox(FT_Bytes table,OTV_Validator otvalid)682   otv_u_C_x_Ox( FT_Bytes       table,
683                 OTV_Validator  otvalid )
684   {
685     FT_Bytes           p = table;
686     FT_UInt            Count, Coverage;
687     OTV_Validate_Func  func;
688 
689 
690     OTV_ENTER;
691 
692     p += 2;     /* skip Format */
693 
694     OTV_LIMIT_CHECK( 4 );
695     Coverage = FT_NEXT_USHORT( p );
696     Count    = FT_NEXT_USHORT( p );
697 
698     OTV_TRACE(( " (Count = %d)\n", Count ));
699 
700     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)Count );
701 
702     OTV_LIMIT_CHECK( Count * 2 );
703 
704     otvalid->nesting_level++;
705     func = otvalid->func[otvalid->nesting_level];
706 
707     for ( ; Count > 0; Count-- )
708       func( table + FT_NEXT_USHORT( p ), otvalid );
709 
710     otvalid->nesting_level--;
711 
712     OTV_EXIT;
713   }
714 
715 
716   /* uses otvalid->extra1 (if > 0: array value limit) */
717 
718   FT_LOCAL_DEF( void )
otv_x_ux(FT_Bytes table,OTV_Validator otvalid)719   otv_x_ux( FT_Bytes       table,
720             OTV_Validator  otvalid )
721   {
722     FT_Bytes  p = table;
723     FT_UInt   Count;
724 
725 
726     OTV_ENTER;
727 
728     OTV_LIMIT_CHECK( 2 );
729     Count = FT_NEXT_USHORT( p );
730 
731     OTV_TRACE(( " (Count = %d)\n", Count ));
732 
733     OTV_LIMIT_CHECK( Count * 2 );
734 
735     if ( otvalid->extra1 )
736     {
737       for ( ; Count > 0; Count-- )
738         if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
739           FT_INVALID_DATA;
740     }
741 
742     OTV_EXIT;
743   }
744 
745 
746   /* `ux' in the function's name is not really correct since only x-1 */
747   /* elements are tested                                              */
748 
749   /* uses otvalid->extra1 (array value limit) */
750 
751   FT_LOCAL_DEF( void )
otv_x_y_ux_sy(FT_Bytes table,OTV_Validator otvalid)752   otv_x_y_ux_sy( FT_Bytes       table,
753                  OTV_Validator  otvalid )
754   {
755     FT_Bytes  p = table;
756     FT_UInt   Count1, Count2;
757 
758 
759     OTV_ENTER;
760 
761     OTV_LIMIT_CHECK( 4 );
762     Count1 = FT_NEXT_USHORT( p );
763     Count2 = FT_NEXT_USHORT( p );
764 
765     OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
766     OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
767 
768     if ( Count1 == 0 )
769       FT_INVALID_DATA;
770 
771     OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
772     p += ( Count1 - 1 ) * 2;
773 
774     for ( ; Count2 > 0; Count2-- )
775     {
776       if ( FT_NEXT_USHORT( p ) >= Count1 )
777         FT_INVALID_DATA;
778 
779       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
780         FT_INVALID_DATA;
781     }
782 
783     OTV_EXIT;
784   }
785 
786 
787   /* `uy' in the function's name is not really correct since only y-1 */
788   /* elements are tested                                              */
789 
790   /* uses otvalid->extra1 (array value limit) */
791 
792   FT_LOCAL_DEF( void )
otv_x_ux_y_uy_z_uz_p_sp(FT_Bytes table,OTV_Validator otvalid)793   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
794                            OTV_Validator  otvalid )
795   {
796     FT_Bytes  p = table;
797     FT_UInt   BacktrackCount, InputCount, LookaheadCount;
798     FT_UInt   Count;
799 
800 
801     OTV_ENTER;
802 
803     OTV_LIMIT_CHECK( 2 );
804     BacktrackCount = FT_NEXT_USHORT( p );
805 
806     OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
807 
808     OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
809     p += BacktrackCount * 2;
810 
811     InputCount = FT_NEXT_USHORT( p );
812     if ( InputCount == 0 )
813       FT_INVALID_DATA;
814 
815     OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
816 
817     OTV_LIMIT_CHECK( InputCount * 2 );
818     p += ( InputCount - 1 ) * 2;
819 
820     LookaheadCount = FT_NEXT_USHORT( p );
821 
822     OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
823 
824     OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
825     p += LookaheadCount * 2;
826 
827     Count = FT_NEXT_USHORT( p );
828 
829     OTV_TRACE(( " (Count = %d)\n", Count ));
830 
831     OTV_LIMIT_CHECK( Count * 4 );
832 
833     for ( ; Count > 0; Count-- )
834     {
835       if ( FT_NEXT_USHORT( p ) >= InputCount )
836         FT_INVALID_DATA;
837 
838       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
839         FT_INVALID_DATA;
840     }
841 
842     OTV_EXIT;
843   }
844 
845 
846   /* sets otvalid->extra1 (valid->lookup_count) */
847 
848   FT_LOCAL_DEF( void )
otv_u_O_O_x_Onx(FT_Bytes table,OTV_Validator otvalid)849   otv_u_O_O_x_Onx( FT_Bytes       table,
850                    OTV_Validator  otvalid )
851   {
852     FT_Bytes           p = table;
853     FT_UInt            Coverage, ClassDef, ClassSetCount;
854     OTV_Validate_Func  func;
855 
856 
857     OTV_ENTER;
858 
859     p += 2;     /* skip Format */
860 
861     OTV_LIMIT_CHECK( 6 );
862     Coverage      = FT_NEXT_USHORT( p );
863     ClassDef      = FT_NEXT_USHORT( p );
864     ClassSetCount = FT_NEXT_USHORT( p );
865 
866     OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
867 
868     otv_Coverage_validate( table + Coverage, otvalid, -1 );
869     otv_ClassDef_validate( table + ClassDef, otvalid );
870 
871     OTV_LIMIT_CHECK( ClassSetCount * 2 );
872 
873     otvalid->nesting_level++;
874     func          = otvalid->func[otvalid->nesting_level];
875     otvalid->extra1 = otvalid->lookup_count;
876 
877     for ( ; ClassSetCount > 0; ClassSetCount-- )
878     {
879       FT_UInt  offset = FT_NEXT_USHORT( p );
880 
881 
882       if ( offset )
883         func( table + offset, otvalid );
884     }
885 
886     otvalid->nesting_level--;
887 
888     OTV_EXIT;
889   }
890 
891 
892   /* uses otvalid->lookup_count */
893 
894   FT_LOCAL_DEF( void )
otv_u_x_y_Ox_sy(FT_Bytes table,OTV_Validator otvalid)895   otv_u_x_y_Ox_sy( FT_Bytes       table,
896                    OTV_Validator  otvalid )
897   {
898     FT_Bytes  p = table;
899     FT_UInt   GlyphCount, Count, count1;
900 
901 
902     OTV_ENTER;
903 
904     p += 2;     /* skip Format */
905 
906     OTV_LIMIT_CHECK( 4 );
907     GlyphCount = FT_NEXT_USHORT( p );
908     Count      = FT_NEXT_USHORT( p );
909 
910     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
911     OTV_TRACE(( " (Count = %d)\n",      Count      ));
912 
913     OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
914 
915     for ( count1 = GlyphCount; count1 > 0; count1-- )
916       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
917 
918     for ( ; Count > 0; Count-- )
919     {
920       if ( FT_NEXT_USHORT( p ) >= GlyphCount )
921         FT_INVALID_DATA;
922 
923       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
924         FT_INVALID_DATA;
925     }
926 
927     OTV_EXIT;
928   }
929 
930 
931   /* sets otvalid->extra1 (valid->lookup_count)    */
932 
933   FT_LOCAL_DEF( void )
otv_u_O_O_O_O_x_Onx(FT_Bytes table,OTV_Validator otvalid)934   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
935                        OTV_Validator  otvalid )
936   {
937     FT_Bytes           p = table;
938     FT_UInt            Coverage;
939     FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
940     FT_UInt            ChainClassSetCount;
941     OTV_Validate_Func  func;
942 
943 
944     OTV_ENTER;
945 
946     p += 2;     /* skip Format */
947 
948     OTV_LIMIT_CHECK( 10 );
949     Coverage           = FT_NEXT_USHORT( p );
950     BacktrackClassDef  = FT_NEXT_USHORT( p );
951     InputClassDef      = FT_NEXT_USHORT( p );
952     LookaheadClassDef  = FT_NEXT_USHORT( p );
953     ChainClassSetCount = FT_NEXT_USHORT( p );
954 
955     OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
956 
957     otv_Coverage_validate( table + Coverage, otvalid, -1 );
958 
959     otv_ClassDef_validate( table + BacktrackClassDef,  otvalid );
960     otv_ClassDef_validate( table + InputClassDef, otvalid );
961     otv_ClassDef_validate( table + LookaheadClassDef, otvalid );
962 
963     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
964 
965     otvalid->nesting_level++;
966     func          = otvalid->func[otvalid->nesting_level];
967     otvalid->extra1 = otvalid->lookup_count;
968 
969     for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
970     {
971       FT_UInt  offset = FT_NEXT_USHORT( p );
972 
973 
974       if ( offset )
975         func( table + offset, otvalid );
976     }
977 
978     otvalid->nesting_level--;
979 
980     OTV_EXIT;
981   }
982 
983 
984   /* uses otvalid->lookup_count */
985 
986   FT_LOCAL_DEF( void )
otv_u_x_Ox_y_Oy_z_Oz_p_sp(FT_Bytes table,OTV_Validator otvalid)987   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
988                              OTV_Validator  otvalid )
989   {
990     FT_Bytes  p = table;
991     FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
992     FT_UInt   count1, count2;
993 
994 
995     OTV_ENTER;
996 
997     p += 2;     /* skip Format */
998 
999     OTV_LIMIT_CHECK( 2 );
1000     BacktrackGlyphCount = FT_NEXT_USHORT( p );
1001 
1002     OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
1003 
1004     OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
1005 
1006     for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
1007       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
1008 
1009     InputGlyphCount = FT_NEXT_USHORT( p );
1010 
1011     OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
1012 
1013     OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
1014 
1015     for ( count1 = InputGlyphCount; count1 > 0; count1-- )
1016       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
1017 
1018     LookaheadGlyphCount = FT_NEXT_USHORT( p );
1019 
1020     OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
1021 
1022     OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
1023 
1024     for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
1025       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
1026 
1027     count2 = FT_NEXT_USHORT( p );
1028 
1029     OTV_TRACE(( " (Count = %d)\n", count2 ));
1030 
1031     OTV_LIMIT_CHECK( count2 * 4 );
1032 
1033     for ( ; count2 > 0; count2-- )
1034     {
1035       if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
1036         FT_INVALID_DATA;
1037 
1038       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
1039         FT_INVALID_DATA;
1040     }
1041 
1042     OTV_EXIT;
1043   }
1044 
1045 
1046   FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_get_Lookup_count(FT_Bytes table)1047   otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
1048   {
1049     FT_Bytes  p = table + 8;
1050 
1051 
1052     return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
1053   }
1054 
1055 
1056   FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_have_MarkAttachmentType_flag(FT_Bytes table)1057   otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
1058   {
1059     FT_Bytes  p, lookup;
1060     FT_UInt   count;
1061 
1062 
1063     if ( !table )
1064       return 0;
1065 
1066     /* LookupList */
1067     p      = table + 8;
1068     table += FT_NEXT_USHORT( p );
1069 
1070     /* LookupCount */
1071     p     = table;
1072     count = FT_NEXT_USHORT( p );
1073 
1074     for ( ; count > 0; count-- )
1075     {
1076       FT_Bytes  oldp;
1077 
1078 
1079       /* Lookup */
1080       lookup = table + FT_NEXT_USHORT( p );
1081 
1082       oldp = p;
1083 
1084       /* LookupFlag */
1085       p = lookup + 2;
1086       if ( FT_NEXT_USHORT( p ) & 0xFF00U )
1087         return 1;
1088 
1089       p = oldp;
1090     }
1091 
1092     return 0;
1093   }
1094 
1095 
1096 /* END */
1097