Initialize Tizen 2.3
[framework/graphics/freetype.git] / src / otvalid / otvcommn.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  otvcommn.c                                                             */
4 /*                                                                         */
5 /*    OpenType common tables validation (body).                            */
6 /*                                                                         */
7 /*  Copyright 2004, 2005, 2006, 2007 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 )
41   otv_Coverage_validate( FT_Bytes       table,
42                          OTV_Validator  valid,
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 >= valid->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 >= valid->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 )
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 )
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 )
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 )
221   otv_ClassDef_validate( FT_Bytes       table,
222                          OTV_Validator  valid )
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 >= valid->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 >= valid->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 )
307   otv_Device_validate( FT_Bytes       table,
308                        OTV_Validator  valid )
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 valid->type_count */
343   /* uses valid->type_funcs */
344
345   FT_LOCAL_DEF( void )
346   otv_Lookup_validate( FT_Bytes       table,
347                        OTV_Validator  valid )
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 > valid->type_count )
364       FT_INVALID_DATA;
365
366     validate = valid->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 ), valid );
375
376     OTV_EXIT;
377   }
378
379
380   /* uses valid->lookup_count */
381
382   FT_LOCAL_DEF( void )
383   otv_LookupList_validate( FT_Bytes       table,
384                            OTV_Validator  valid )
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     valid->lookup_count = LookupCount;
400
401     /* Lookup */
402     for ( ; LookupCount > 0; LookupCount-- )
403       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
404
405     OTV_EXIT;
406   }
407
408
409   static FT_UInt
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 valid->lookup_count */
425
426   FT_LOCAL_DEF( void )
427   otv_Feature_validate( FT_Bytes       table,
428                         OTV_Validator  valid )
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 ) >= valid->lookup_count )
447         FT_INVALID_DATA;
448
449     OTV_EXIT;
450   }
451
452
453   static FT_UInt
454   otv_Feature_get_count( FT_Bytes  table )
455   {
456     return FT_NEXT_USHORT( table );
457   }
458
459
460   /* sets valid->lookup_count */
461
462   FT_LOCAL_DEF( void )
463   otv_FeatureList_validate( FT_Bytes       table,
464                             FT_Bytes       lookups,
465                             OTV_Validator  valid )
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     valid->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 ), valid );
489     }
490
491     OTV_EXIT;
492   }
493
494
495   /*************************************************************************/
496   /*************************************************************************/
497   /*****                                                               *****/
498   /*****                       LANGUAGE SYSTEM                         *****/
499   /*****                                                               *****/
500   /*************************************************************************/
501   /*************************************************************************/
502
503
504   /* uses valid->extra1 (number of features) */
505
506   FT_LOCAL_DEF( void )
507   otv_LangSys_validate( FT_Bytes       table,
508                         OTV_Validator  valid )
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 >= valid->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 ) >= valid->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 )
548   otv_Script_validate( FT_Bytes       table,
549                        OTV_Validator  valid )
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, valid );
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 ), valid );
575     }
576
577     OTV_EXIT;
578   }
579
580
581   /* sets valid->extra1 (number of features) */
582
583   FT_LOCAL_DEF( void )
584   otv_ScriptList_validate( FT_Bytes       table,
585                            FT_Bytes       features,
586                            OTV_Validator  valid )
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     valid->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 ), valid ); /* 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 )
642   otv_x_Ox( FT_Bytes       table,
643             OTV_Validator  valid )
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     valid->nesting_level++;
660     func = valid->func[valid->nesting_level];
661
662     for ( ; Count > 0; Count-- )
663       func( table + FT_NEXT_USHORT( p ), valid );
664
665     valid->nesting_level--;
666
667     OTV_EXIT;
668   }
669
670
671   FT_LOCAL_DEF( void )
672   otv_u_C_x_Ox( FT_Bytes       table,
673                 OTV_Validator  valid )
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, valid, Count );
691
692     OTV_LIMIT_CHECK( Count * 2 );
693
694     valid->nesting_level++;
695     func = valid->func[valid->nesting_level];
696
697     for ( ; Count > 0; Count-- )
698       func( table + FT_NEXT_USHORT( p ), valid );
699
700     valid->nesting_level--;
701
702     OTV_EXIT;
703   }
704
705
706   /* uses valid->extra1 (if > 0: array value limit) */
707
708   FT_LOCAL_DEF( void )
709   otv_x_ux( FT_Bytes       table,
710             OTV_Validator  valid )
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 ( valid->extra1 )
726     {
727       for ( ; Count > 0; Count-- )
728         if ( FT_NEXT_USHORT( p ) >= valid->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 valid->extra1 (array value limit) */
740
741   FT_LOCAL_DEF( void )
742   otv_x_y_ux_sy( FT_Bytes       table,
743                  OTV_Validator  valid )
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 ) >= valid->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 valid->extra1 (array value limit) */
781
782   FT_LOCAL_DEF( void )
783   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
784                            OTV_Validator  valid )
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 ) >= valid->extra1 )
829         FT_INVALID_DATA;
830     }
831
832     OTV_EXIT;
833   }
834
835
836   /* sets valid->extra1 (valid->lookup_count) */
837
838   FT_LOCAL_DEF( void )
839   otv_u_O_O_x_Onx( FT_Bytes       table,
840                    OTV_Validator  valid )
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, valid, -1 );
859     otv_ClassDef_validate( table + ClassDef, valid );
860
861     OTV_LIMIT_CHECK( ClassSetCount * 2 );
862
863     valid->nesting_level++;
864     func          = valid->func[valid->nesting_level];
865     valid->extra1 = valid->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, valid );
874     }
875
876     valid->nesting_level--;
877
878     OTV_EXIT;
879   }
880
881
882   /* uses valid->lookup_count */
883
884   FT_LOCAL_DEF( void )
885   otv_u_x_y_Ox_sy( FT_Bytes       table,
886                    OTV_Validator  valid )
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 ), valid, -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 ) >= valid->lookup_count )
914         FT_INVALID_DATA;
915     }
916
917     OTV_EXIT;
918   }
919
920
921   /* sets valid->extra1 (valid->lookup_count)    */
922
923   FT_LOCAL_DEF( void )
924   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
925                        OTV_Validator  valid )
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, valid, -1 );
948
949     otv_ClassDef_validate( table + BacktrackClassDef,  valid );
950     otv_ClassDef_validate( table + InputClassDef, valid );
951     otv_ClassDef_validate( table + LookaheadClassDef, valid );
952
953     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
954
955     valid->nesting_level++;
956     func          = valid->func[valid->nesting_level];
957     valid->extra1 = valid->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, valid );
966     }
967
968     valid->nesting_level--;
969
970     OTV_EXIT;
971   }
972
973
974   /* uses valid->lookup_count */
975
976   FT_LOCAL_DEF( void )
977   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
978                              OTV_Validator  valid )
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 ), valid, -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 ), valid, -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 ), valid, -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 ) >= valid->lookup_count )
1029         FT_INVALID_DATA;
1030     }
1031
1032     OTV_EXIT;
1033   }
1034
1035
1036   FT_LOCAL_DEF( FT_UInt )
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 )
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 */