1/****************************************************************************
2 *
3 * otvcommn.c
4 *
5 * OpenType common tables validation (body).
6 *
7 * Copyright (C) 2004-2023 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 )
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 )
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 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 )
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 )
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 )
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 )
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 )
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
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 )
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
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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