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