• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  otvcommn.c                                                             */
4 /*                                                                         */
5 /*    OpenType common tables validation (body).                            */
6 /*                                                                         */
7 /*  Copyright 2004-2015 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  trace_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( 8 );
317     StartSize   = FT_NEXT_USHORT( p );
318     EndSize     = FT_NEXT_USHORT( p );
319     DeltaFormat = FT_NEXT_USHORT( p );
320 
321     if ( DeltaFormat < 1 || DeltaFormat > 3 )
322       FT_INVALID_FORMAT;
323 
324     if ( EndSize < StartSize )
325       FT_INVALID_DATA;
326 
327     count = EndSize - StartSize + 1;
328     OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
329 
330     OTV_EXIT;
331   }
332 
333 
334   /*************************************************************************/
335   /*************************************************************************/
336   /*****                                                               *****/
337   /*****                         LOOKUPS                               *****/
338   /*****                                                               *****/
339   /*************************************************************************/
340   /*************************************************************************/
341 
342   /* uses otvalid->type_count */
343   /* uses otvalid->type_funcs */
344 
345   FT_LOCAL_DEF( void )
otv_Lookup_validate(FT_Bytes table,OTV_Validator otvalid)346   otv_Lookup_validate( FT_Bytes       table,
347                        OTV_Validator  otvalid )
348   {
349     FT_Bytes           p = table;
350     FT_UInt            LookupType, SubTableCount;
351     OTV_Validate_Func  validate;
352 
353 
354     OTV_NAME_ENTER( "Lookup" );
355 
356     OTV_LIMIT_CHECK( 6 );
357     LookupType    = FT_NEXT_USHORT( p );
358     p            += 2;                      /* skip LookupFlag */
359     SubTableCount = FT_NEXT_USHORT( p );
360 
361     OTV_TRACE(( " (type %d)\n", LookupType ));
362 
363     if ( LookupType == 0 || LookupType > otvalid->type_count )
364       FT_INVALID_DATA;
365 
366     validate = otvalid->type_funcs[LookupType - 1];
367 
368     OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
369 
370     OTV_LIMIT_CHECK( SubTableCount * 2 );
371 
372     /* SubTable */
373     for ( ; SubTableCount > 0; SubTableCount-- )
374       validate( table + FT_NEXT_USHORT( p ), otvalid );
375 
376     OTV_EXIT;
377   }
378 
379 
380   /* uses valid->lookup_count */
381 
382   FT_LOCAL_DEF( void )
otv_LookupList_validate(FT_Bytes table,OTV_Validator otvalid)383   otv_LookupList_validate( FT_Bytes       table,
384                            OTV_Validator  otvalid )
385   {
386     FT_Bytes  p = table;
387     FT_UInt   LookupCount;
388 
389 
390     OTV_NAME_ENTER( "LookupList" );
391 
392     OTV_LIMIT_CHECK( 2 );
393     LookupCount = FT_NEXT_USHORT( p );
394 
395     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
396 
397     OTV_LIMIT_CHECK( LookupCount * 2 );
398 
399     otvalid->lookup_count = LookupCount;
400 
401     /* Lookup */
402     for ( ; LookupCount > 0; LookupCount-- )
403       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), otvalid );
404 
405     OTV_EXIT;
406   }
407 
408 
409   static FT_UInt
otv_LookupList_get_count(FT_Bytes table)410   otv_LookupList_get_count( FT_Bytes  table )
411   {
412     return FT_NEXT_USHORT( table );
413   }
414 
415 
416   /*************************************************************************/
417   /*************************************************************************/
418   /*****                                                               *****/
419   /*****                        FEATURES                               *****/
420   /*****                                                               *****/
421   /*************************************************************************/
422   /*************************************************************************/
423 
424   /* uses otvalid->lookup_count */
425 
426   FT_LOCAL_DEF( void )
otv_Feature_validate(FT_Bytes table,OTV_Validator otvalid)427   otv_Feature_validate( FT_Bytes       table,
428                         OTV_Validator  otvalid )
429   {
430     FT_Bytes  p = table;
431     FT_UInt   LookupCount;
432 
433 
434     OTV_NAME_ENTER( "Feature" );
435 
436     OTV_LIMIT_CHECK( 4 );
437     p           += 2;                   /* skip FeatureParams (unused) */
438     LookupCount  = FT_NEXT_USHORT( p );
439 
440     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
441 
442     OTV_LIMIT_CHECK( LookupCount * 2 );
443 
444     /* LookupListIndex */
445     for ( ; LookupCount > 0; LookupCount-- )
446       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
447         FT_INVALID_DATA;
448 
449     OTV_EXIT;
450   }
451 
452 
453   static FT_UInt
otv_Feature_get_count(FT_Bytes table)454   otv_Feature_get_count( FT_Bytes  table )
455   {
456     return FT_NEXT_USHORT( table );
457   }
458 
459 
460   /* sets otvalid->lookup_count */
461 
462   FT_LOCAL_DEF( void )
otv_FeatureList_validate(FT_Bytes table,FT_Bytes lookups,OTV_Validator otvalid)463   otv_FeatureList_validate( FT_Bytes       table,
464                             FT_Bytes       lookups,
465                             OTV_Validator  otvalid )
466   {
467     FT_Bytes  p = table;
468     FT_UInt   FeatureCount;
469 
470 
471     OTV_NAME_ENTER( "FeatureList" );
472 
473     OTV_LIMIT_CHECK( 2 );
474     FeatureCount = FT_NEXT_USHORT( p );
475 
476     OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
477 
478     OTV_LIMIT_CHECK( FeatureCount * 2 );
479 
480     otvalid->lookup_count = otv_LookupList_get_count( lookups );
481 
482     /* FeatureRecord */
483     for ( ; FeatureCount > 0; FeatureCount-- )
484     {
485       p += 4;       /* skip FeatureTag */
486 
487       /* Feature */
488       otv_Feature_validate( table + FT_NEXT_USHORT( p ), otvalid );
489     }
490 
491     OTV_EXIT;
492   }
493 
494 
495   /*************************************************************************/
496   /*************************************************************************/
497   /*****                                                               *****/
498   /*****                       LANGUAGE SYSTEM                         *****/
499   /*****                                                               *****/
500   /*************************************************************************/
501   /*************************************************************************/
502 
503 
504   /* uses otvalid->extra1 (number of features) */
505 
506   FT_LOCAL_DEF( void )
otv_LangSys_validate(FT_Bytes table,OTV_Validator otvalid)507   otv_LangSys_validate( FT_Bytes       table,
508                         OTV_Validator  otvalid )
509   {
510     FT_Bytes  p = table;
511     FT_UInt   ReqFeatureIndex;
512     FT_UInt   FeatureCount;
513 
514 
515     OTV_NAME_ENTER( "LangSys" );
516 
517     OTV_LIMIT_CHECK( 6 );
518     p              += 2;                    /* skip LookupOrder (unused) */
519     ReqFeatureIndex = FT_NEXT_USHORT( p );
520     FeatureCount    = FT_NEXT_USHORT( p );
521 
522     OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
523     OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
524 
525     if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= otvalid->extra1 )
526       FT_INVALID_DATA;
527 
528     OTV_LIMIT_CHECK( FeatureCount * 2 );
529 
530     /* FeatureIndex */
531     for ( ; FeatureCount > 0; FeatureCount-- )
532       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
533         FT_INVALID_DATA;
534 
535     OTV_EXIT;
536   }
537 
538 
539   /*************************************************************************/
540   /*************************************************************************/
541   /*****                                                               *****/
542   /*****                           SCRIPTS                             *****/
543   /*****                                                               *****/
544   /*************************************************************************/
545   /*************************************************************************/
546 
547   FT_LOCAL_DEF( void )
otv_Script_validate(FT_Bytes table,OTV_Validator otvalid)548   otv_Script_validate( FT_Bytes       table,
549                        OTV_Validator  otvalid )
550   {
551     FT_UInt   DefaultLangSys, LangSysCount;
552     FT_Bytes  p = table;
553 
554 
555     OTV_NAME_ENTER( "Script" );
556 
557     OTV_LIMIT_CHECK( 4 );
558     DefaultLangSys = FT_NEXT_USHORT( p );
559     LangSysCount   = FT_NEXT_USHORT( p );
560 
561     OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
562 
563     if ( DefaultLangSys != 0 )
564       otv_LangSys_validate( table + DefaultLangSys, otvalid );
565 
566     OTV_LIMIT_CHECK( LangSysCount * 6 );
567 
568     /* LangSysRecord */
569     for ( ; LangSysCount > 0; LangSysCount-- )
570     {
571       p += 4;       /* skip LangSysTag */
572 
573       /* LangSys */
574       otv_LangSys_validate( table + FT_NEXT_USHORT( p ), otvalid );
575     }
576 
577     OTV_EXIT;
578   }
579 
580 
581   /* sets otvalid->extra1 (number of features) */
582 
583   FT_LOCAL_DEF( void )
otv_ScriptList_validate(FT_Bytes table,FT_Bytes features,OTV_Validator otvalid)584   otv_ScriptList_validate( FT_Bytes       table,
585                            FT_Bytes       features,
586                            OTV_Validator  otvalid )
587   {
588     FT_UInt   ScriptCount;
589     FT_Bytes  p = table;
590 
591 
592     OTV_NAME_ENTER( "ScriptList" );
593 
594     OTV_LIMIT_CHECK( 2 );
595     ScriptCount = FT_NEXT_USHORT( p );
596 
597     OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
598 
599     OTV_LIMIT_CHECK( ScriptCount * 6 );
600 
601     otvalid->extra1 = otv_Feature_get_count( features );
602 
603     /* ScriptRecord */
604     for ( ; ScriptCount > 0; ScriptCount-- )
605     {
606       p += 4;       /* skip ScriptTag */
607 
608       otv_Script_validate( table + FT_NEXT_USHORT( p ), otvalid ); /* Script */
609     }
610 
611     OTV_EXIT;
612   }
613 
614 
615   /*************************************************************************/
616   /*************************************************************************/
617   /*****                                                               *****/
618   /*****                      UTILITY FUNCTIONS                        *****/
619   /*****                                                               *****/
620   /*************************************************************************/
621   /*************************************************************************/
622 
623   /*
624      u:   uint16
625      ux:  unit16 [x]
626 
627      s:   struct
628      sx:  struct [x]
629      sxy: struct [x], using external y count
630 
631      x:   uint16 x
632 
633      C:   Coverage
634 
635      O:   Offset
636      On:  Offset (NULL)
637      Ox:  Offset [x]
638      Onx: Offset (NULL) [x]
639   */
640 
641   FT_LOCAL_DEF( void )
otv_x_Ox(FT_Bytes table,OTV_Validator otvalid)642   otv_x_Ox( FT_Bytes       table,
643             OTV_Validator  otvalid )
644   {
645     FT_Bytes           p = table;
646     FT_UInt            Count;
647     OTV_Validate_Func  func;
648 
649 
650     OTV_ENTER;
651 
652     OTV_LIMIT_CHECK( 2 );
653     Count = FT_NEXT_USHORT( p );
654 
655     OTV_TRACE(( " (Count = %d)\n", Count ));
656 
657     OTV_LIMIT_CHECK( Count * 2 );
658 
659     otvalid->nesting_level++;
660     func = otvalid->func[otvalid->nesting_level];
661 
662     for ( ; Count > 0; Count-- )
663       func( table + FT_NEXT_USHORT( p ), otvalid );
664 
665     otvalid->nesting_level--;
666 
667     OTV_EXIT;
668   }
669 
670 
671   FT_LOCAL_DEF( void )
otv_u_C_x_Ox(FT_Bytes table,OTV_Validator otvalid)672   otv_u_C_x_Ox( FT_Bytes       table,
673                 OTV_Validator  otvalid )
674   {
675     FT_Bytes           p = table;
676     FT_UInt            Count, Coverage;
677     OTV_Validate_Func  func;
678 
679 
680     OTV_ENTER;
681 
682     p += 2;     /* skip Format */
683 
684     OTV_LIMIT_CHECK( 4 );
685     Coverage = FT_NEXT_USHORT( p );
686     Count    = FT_NEXT_USHORT( p );
687 
688     OTV_TRACE(( " (Count = %d)\n", Count ));
689 
690     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)Count );
691 
692     OTV_LIMIT_CHECK( Count * 2 );
693 
694     otvalid->nesting_level++;
695     func = otvalid->func[otvalid->nesting_level];
696 
697     for ( ; Count > 0; Count-- )
698       func( table + FT_NEXT_USHORT( p ), otvalid );
699 
700     otvalid->nesting_level--;
701 
702     OTV_EXIT;
703   }
704 
705 
706   /* uses otvalid->extra1 (if > 0: array value limit) */
707 
708   FT_LOCAL_DEF( void )
otv_x_ux(FT_Bytes table,OTV_Validator otvalid)709   otv_x_ux( FT_Bytes       table,
710             OTV_Validator  otvalid )
711   {
712     FT_Bytes  p = table;
713     FT_UInt   Count;
714 
715 
716     OTV_ENTER;
717 
718     OTV_LIMIT_CHECK( 2 );
719     Count = FT_NEXT_USHORT( p );
720 
721     OTV_TRACE(( " (Count = %d)\n", Count ));
722 
723     OTV_LIMIT_CHECK( Count * 2 );
724 
725     if ( otvalid->extra1 )
726     {
727       for ( ; Count > 0; Count-- )
728         if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
729           FT_INVALID_DATA;
730     }
731 
732     OTV_EXIT;
733   }
734 
735 
736   /* `ux' in the function's name is not really correct since only x-1 */
737   /* elements are tested                                              */
738 
739   /* uses otvalid->extra1 (array value limit) */
740 
741   FT_LOCAL_DEF( void )
otv_x_y_ux_sy(FT_Bytes table,OTV_Validator otvalid)742   otv_x_y_ux_sy( FT_Bytes       table,
743                  OTV_Validator  otvalid )
744   {
745     FT_Bytes  p = table;
746     FT_UInt   Count1, Count2;
747 
748 
749     OTV_ENTER;
750 
751     OTV_LIMIT_CHECK( 4 );
752     Count1 = FT_NEXT_USHORT( p );
753     Count2 = FT_NEXT_USHORT( p );
754 
755     OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
756     OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
757 
758     if ( Count1 == 0 )
759       FT_INVALID_DATA;
760 
761     OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
762     p += ( Count1 - 1 ) * 2;
763 
764     for ( ; Count2 > 0; Count2-- )
765     {
766       if ( FT_NEXT_USHORT( p ) >= Count1 )
767         FT_INVALID_DATA;
768 
769       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
770         FT_INVALID_DATA;
771     }
772 
773     OTV_EXIT;
774   }
775 
776 
777   /* `uy' in the function's name is not really correct since only y-1 */
778   /* elements are tested                                              */
779 
780   /* uses otvalid->extra1 (array value limit) */
781 
782   FT_LOCAL_DEF( void )
otv_x_ux_y_uy_z_uz_p_sp(FT_Bytes table,OTV_Validator otvalid)783   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
784                            OTV_Validator  otvalid )
785   {
786     FT_Bytes  p = table;
787     FT_UInt   BacktrackCount, InputCount, LookaheadCount;
788     FT_UInt   Count;
789 
790 
791     OTV_ENTER;
792 
793     OTV_LIMIT_CHECK( 2 );
794     BacktrackCount = FT_NEXT_USHORT( p );
795 
796     OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
797 
798     OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
799     p += BacktrackCount * 2;
800 
801     InputCount = FT_NEXT_USHORT( p );
802     if ( InputCount == 0 )
803       FT_INVALID_DATA;
804 
805     OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
806 
807     OTV_LIMIT_CHECK( InputCount * 2 );
808     p += ( InputCount - 1 ) * 2;
809 
810     LookaheadCount = FT_NEXT_USHORT( p );
811 
812     OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
813 
814     OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
815     p += LookaheadCount * 2;
816 
817     Count = FT_NEXT_USHORT( p );
818 
819     OTV_TRACE(( " (Count = %d)\n", Count ));
820 
821     OTV_LIMIT_CHECK( Count * 4 );
822 
823     for ( ; Count > 0; Count-- )
824     {
825       if ( FT_NEXT_USHORT( p ) >= InputCount )
826         FT_INVALID_DATA;
827 
828       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
829         FT_INVALID_DATA;
830     }
831 
832     OTV_EXIT;
833   }
834 
835 
836   /* sets otvalid->extra1 (valid->lookup_count) */
837 
838   FT_LOCAL_DEF( void )
otv_u_O_O_x_Onx(FT_Bytes table,OTV_Validator otvalid)839   otv_u_O_O_x_Onx( FT_Bytes       table,
840                    OTV_Validator  otvalid )
841   {
842     FT_Bytes           p = table;
843     FT_UInt            Coverage, ClassDef, ClassSetCount;
844     OTV_Validate_Func  func;
845 
846 
847     OTV_ENTER;
848 
849     p += 2;     /* skip Format */
850 
851     OTV_LIMIT_CHECK( 6 );
852     Coverage      = FT_NEXT_USHORT( p );
853     ClassDef      = FT_NEXT_USHORT( p );
854     ClassSetCount = FT_NEXT_USHORT( p );
855 
856     OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
857 
858     otv_Coverage_validate( table + Coverage, otvalid, -1 );
859     otv_ClassDef_validate( table + ClassDef, otvalid );
860 
861     OTV_LIMIT_CHECK( ClassSetCount * 2 );
862 
863     otvalid->nesting_level++;
864     func          = otvalid->func[otvalid->nesting_level];
865     otvalid->extra1 = otvalid->lookup_count;
866 
867     for ( ; ClassSetCount > 0; ClassSetCount-- )
868     {
869       FT_UInt  offset = FT_NEXT_USHORT( p );
870 
871 
872       if ( offset )
873         func( table + offset, otvalid );
874     }
875 
876     otvalid->nesting_level--;
877 
878     OTV_EXIT;
879   }
880 
881 
882   /* uses otvalid->lookup_count */
883 
884   FT_LOCAL_DEF( void )
otv_u_x_y_Ox_sy(FT_Bytes table,OTV_Validator otvalid)885   otv_u_x_y_Ox_sy( FT_Bytes       table,
886                    OTV_Validator  otvalid )
887   {
888     FT_Bytes  p = table;
889     FT_UInt   GlyphCount, Count, count1;
890 
891 
892     OTV_ENTER;
893 
894     p += 2;     /* skip Format */
895 
896     OTV_LIMIT_CHECK( 4 );
897     GlyphCount = FT_NEXT_USHORT( p );
898     Count      = FT_NEXT_USHORT( p );
899 
900     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
901     OTV_TRACE(( " (Count = %d)\n",      Count      ));
902 
903     OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
904 
905     for ( count1 = GlyphCount; count1 > 0; count1-- )
906       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
907 
908     for ( ; Count > 0; Count-- )
909     {
910       if ( FT_NEXT_USHORT( p ) >= GlyphCount )
911         FT_INVALID_DATA;
912 
913       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
914         FT_INVALID_DATA;
915     }
916 
917     OTV_EXIT;
918   }
919 
920 
921   /* sets otvalid->extra1 (valid->lookup_count)    */
922 
923   FT_LOCAL_DEF( void )
otv_u_O_O_O_O_x_Onx(FT_Bytes table,OTV_Validator otvalid)924   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
925                        OTV_Validator  otvalid )
926   {
927     FT_Bytes           p = table;
928     FT_UInt            Coverage;
929     FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
930     FT_UInt            ChainClassSetCount;
931     OTV_Validate_Func  func;
932 
933 
934     OTV_ENTER;
935 
936     p += 2;     /* skip Format */
937 
938     OTV_LIMIT_CHECK( 10 );
939     Coverage           = FT_NEXT_USHORT( p );
940     BacktrackClassDef  = FT_NEXT_USHORT( p );
941     InputClassDef      = FT_NEXT_USHORT( p );
942     LookaheadClassDef  = FT_NEXT_USHORT( p );
943     ChainClassSetCount = FT_NEXT_USHORT( p );
944 
945     OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
946 
947     otv_Coverage_validate( table + Coverage, otvalid, -1 );
948 
949     otv_ClassDef_validate( table + BacktrackClassDef,  otvalid );
950     otv_ClassDef_validate( table + InputClassDef, otvalid );
951     otv_ClassDef_validate( table + LookaheadClassDef, otvalid );
952 
953     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
954 
955     otvalid->nesting_level++;
956     func          = otvalid->func[otvalid->nesting_level];
957     otvalid->extra1 = otvalid->lookup_count;
958 
959     for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
960     {
961       FT_UInt  offset = FT_NEXT_USHORT( p );
962 
963 
964       if ( offset )
965         func( table + offset, otvalid );
966     }
967 
968     otvalid->nesting_level--;
969 
970     OTV_EXIT;
971   }
972 
973 
974   /* uses otvalid->lookup_count */
975 
976   FT_LOCAL_DEF( void )
otv_u_x_Ox_y_Oy_z_Oz_p_sp(FT_Bytes table,OTV_Validator otvalid)977   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
978                              OTV_Validator  otvalid )
979   {
980     FT_Bytes  p = table;
981     FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
982     FT_UInt   count1, count2;
983 
984 
985     OTV_ENTER;
986 
987     p += 2;     /* skip Format */
988 
989     OTV_LIMIT_CHECK( 2 );
990     BacktrackGlyphCount = FT_NEXT_USHORT( p );
991 
992     OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
993 
994     OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
995 
996     for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
997       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
998 
999     InputGlyphCount = FT_NEXT_USHORT( p );
1000 
1001     OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
1002 
1003     OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
1004 
1005     for ( count1 = InputGlyphCount; count1 > 0; count1-- )
1006       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
1007 
1008     LookaheadGlyphCount = FT_NEXT_USHORT( p );
1009 
1010     OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
1011 
1012     OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
1013 
1014     for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
1015       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
1016 
1017     count2 = FT_NEXT_USHORT( p );
1018 
1019     OTV_TRACE(( " (Count = %d)\n", count2 ));
1020 
1021     OTV_LIMIT_CHECK( count2 * 4 );
1022 
1023     for ( ; count2 > 0; count2-- )
1024     {
1025       if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
1026         FT_INVALID_DATA;
1027 
1028       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
1029         FT_INVALID_DATA;
1030     }
1031 
1032     OTV_EXIT;
1033   }
1034 
1035 
1036   FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_get_Lookup_count(FT_Bytes table)1037   otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
1038   {
1039     FT_Bytes  p = table + 8;
1040 
1041 
1042     return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
1043   }
1044 
1045 
1046   FT_LOCAL_DEF( FT_UInt )
otv_GSUBGPOS_have_MarkAttachmentType_flag(FT_Bytes table)1047   otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
1048   {
1049     FT_Bytes  p, lookup;
1050     FT_UInt   count;
1051 
1052 
1053     if ( !table )
1054       return 0;
1055 
1056     /* LookupList */
1057     p      = table + 8;
1058     table += FT_NEXT_USHORT( p );
1059 
1060     /* LookupCount */
1061     p     = table;
1062     count = FT_NEXT_USHORT( p );
1063 
1064     for ( ; count > 0; count-- )
1065     {
1066       FT_Bytes  oldp;
1067 
1068 
1069       /* Lookup */
1070       lookup = table + FT_NEXT_USHORT( p );
1071 
1072       oldp = p;
1073 
1074       /* LookupFlag */
1075       p = lookup + 2;
1076       if ( FT_NEXT_USHORT( p ) & 0xFF00U )
1077         return 1;
1078 
1079       p = oldp;
1080     }
1081 
1082     return 0;
1083   }
1084 
1085 
1086 /* END */
1087