1 /****************************************************************************
2  *
3  * otvmod.c
4  *
5  *   FreeType's OpenType validation module implementation (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 <freetype/tttables.h>
20 #include <freetype/tttags.h>
21 #include <freetype/ftotval.h>
22 #include <freetype/internal/ftobjs.h>
23 #include <freetype/internal/services/svotval.h>
24 
25 #include "otvmod.h"
26 #include "otvalid.h"
27 #include "otvcommn.h"
28 
29 
30   /**************************************************************************
31    *
32    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
33    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
34    * messages during execution.
35    */
36 #undef  FT_COMPONENT
37 #define FT_COMPONENT  otvmodule
38 
39 
40   static FT_Error
otv_load_table(FT_Face face,FT_Tag tag,FT_Byte * volatile * table,FT_ULong * table_len)41   otv_load_table( FT_Face             face,
42                   FT_Tag              tag,
43                   FT_Byte* volatile*  table,
44                   FT_ULong*           table_len )
45   {
46     FT_Error   error;
47     FT_Memory  memory = FT_FACE_MEMORY( face );
48 
49 
50     error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
51     if ( FT_ERR_EQ( error, Table_Missing ) )
52       return FT_Err_Ok;
53     if ( error )
54       goto Exit;
55 
56     if ( FT_ALLOC( *table, *table_len ) )
57       goto Exit;
58 
59     error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
60 
61   Exit:
62     return error;
63   }
64 
65 
66   static FT_Error
otv_validate(FT_Face volatile face,FT_UInt ot_flags,FT_Bytes * ot_base,FT_Bytes * ot_gdef,FT_Bytes * ot_gpos,FT_Bytes * ot_gsub,FT_Bytes * ot_jstf)67   otv_validate( FT_Face volatile   face,
68                 FT_UInt            ot_flags,
69                 FT_Bytes          *ot_base,
70                 FT_Bytes          *ot_gdef,
71                 FT_Bytes          *ot_gpos,
72                 FT_Bytes          *ot_gsub,
73                 FT_Bytes          *ot_jstf )
74   {
75     FT_Error                  error = FT_Err_Ok;
76     FT_Byte* volatile         base;
77     FT_Byte* volatile         gdef;
78     FT_Byte* volatile         gpos;
79     FT_Byte* volatile         gsub;
80     FT_Byte* volatile         jstf;
81     FT_Byte* volatile         math;
82     FT_ULong                  len_base, len_gdef, len_gpos, len_gsub, len_jstf;
83     FT_ULong                  len_math;
84     FT_UInt                   num_glyphs = (FT_UInt)face->num_glyphs;
85     FT_ValidatorRec volatile  valid;
86 
87 
88     base     = gdef     = gpos     = gsub     = jstf     = math     = NULL;
89     len_base = len_gdef = len_gpos = len_gsub = len_jstf = len_math = 0;
90 
91     /*
92      * XXX: OpenType tables cannot handle 32-bit glyph index,
93      *      although broken TrueType can have 32-bit glyph index.
94      */
95     if ( face->num_glyphs > 0xFFFFL )
96     {
97       FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08x) ",
98                   face->num_glyphs ));
99       FT_TRACE1(( "are not handled by OpenType tables\n" ));
100       num_glyphs = 0xFFFF;
101     }
102 
103     /* load tables */
104 
105     if ( ot_flags & FT_VALIDATE_BASE )
106     {
107       error = otv_load_table( face, TTAG_BASE, &base, &len_base );
108       if ( error )
109         goto Exit;
110     }
111 
112     if ( ot_flags & FT_VALIDATE_GDEF )
113     {
114       error = otv_load_table( face, TTAG_GDEF, &gdef, &len_gdef );
115       if ( error )
116         goto Exit;
117     }
118 
119     if ( ot_flags & FT_VALIDATE_GPOS )
120     {
121       error = otv_load_table( face, TTAG_GPOS, &gpos, &len_gpos );
122       if ( error )
123         goto Exit;
124     }
125 
126     if ( ot_flags & FT_VALIDATE_GSUB )
127     {
128       error = otv_load_table( face, TTAG_GSUB, &gsub, &len_gsub );
129       if ( error )
130         goto Exit;
131     }
132 
133     if ( ot_flags & FT_VALIDATE_JSTF )
134     {
135       error = otv_load_table( face, TTAG_JSTF, &jstf, &len_jstf );
136       if ( error )
137         goto Exit;
138     }
139 
140     if ( ot_flags & FT_VALIDATE_MATH )
141     {
142       error = otv_load_table( face, TTAG_MATH, &math, &len_math );
143       if ( error )
144         goto Exit;
145     }
146 
147     /* validate tables */
148 
149     if ( base )
150     {
151       ft_validator_init( &valid, base, base + len_base, FT_VALIDATE_DEFAULT );
152       if ( ft_setjmp( valid.jump_buffer ) == 0 )
153         otv_BASE_validate( base, &valid );
154       error = valid.error;
155       if ( error )
156         goto Exit;
157     }
158 
159     if ( gpos )
160     {
161       ft_validator_init( &valid, gpos, gpos + len_gpos, FT_VALIDATE_DEFAULT );
162       if ( ft_setjmp( valid.jump_buffer ) == 0 )
163         otv_GPOS_validate( gpos, num_glyphs, &valid );
164       error = valid.error;
165       if ( error )
166         goto Exit;
167     }
168 
169     if ( gsub )
170     {
171       ft_validator_init( &valid, gsub, gsub + len_gsub, FT_VALIDATE_DEFAULT );
172       if ( ft_setjmp( valid.jump_buffer ) == 0 )
173         otv_GSUB_validate( gsub, num_glyphs, &valid );
174       error = valid.error;
175       if ( error )
176         goto Exit;
177     }
178 
179     if ( gdef )
180     {
181       ft_validator_init( &valid, gdef, gdef + len_gdef, FT_VALIDATE_DEFAULT );
182       if ( ft_setjmp( valid.jump_buffer ) == 0 )
183         otv_GDEF_validate( gdef, gsub, gpos, num_glyphs, &valid );
184       error = valid.error;
185       if ( error )
186         goto Exit;
187     }
188 
189     if ( jstf )
190     {
191       ft_validator_init( &valid, jstf, jstf + len_jstf, FT_VALIDATE_DEFAULT );
192       if ( ft_setjmp( valid.jump_buffer ) == 0 )
193         otv_JSTF_validate( jstf, gsub, gpos, num_glyphs, &valid );
194       error = valid.error;
195       if ( error )
196         goto Exit;
197     }
198 
199     if ( math )
200     {
201       ft_validator_init( &valid, math, math + len_math, FT_VALIDATE_DEFAULT );
202       if ( ft_setjmp( valid.jump_buffer ) == 0 )
203         otv_MATH_validate( math, num_glyphs, &valid );
204       error = valid.error;
205       if ( error )
206         goto Exit;
207     }
208 
209     *ot_base = (FT_Bytes)base;
210     *ot_gdef = (FT_Bytes)gdef;
211     *ot_gpos = (FT_Bytes)gpos;
212     *ot_gsub = (FT_Bytes)gsub;
213     *ot_jstf = (FT_Bytes)jstf;
214 
215   Exit:
216     if ( error )
217     {
218       FT_Memory  memory = FT_FACE_MEMORY( face );
219 
220 
221       FT_FREE( base );
222       FT_FREE( gdef );
223       FT_FREE( gpos );
224       FT_FREE( gsub );
225       FT_FREE( jstf );
226     }
227 
228     {
229       FT_Memory  memory = FT_FACE_MEMORY( face );
230 
231 
232       FT_FREE( math );                 /* Can't return this as API is frozen */
233     }
234 
235     return error;
236   }
237 
238 
239   static
240   const FT_Service_OTvalidateRec  otvalid_interface =
241   {
242     otv_validate        /* validate */
243   };
244 
245 
246   static
247   const FT_ServiceDescRec  otvalid_services[] =
248   {
249     { FT_SERVICE_ID_OPENTYPE_VALIDATE, &otvalid_interface },
250     { NULL, NULL }
251   };
252 
253 
254   static FT_Pointer
otvalid_get_service(FT_Module module,const char * service_id)255   otvalid_get_service( FT_Module    module,
256                        const char*  service_id )
257   {
258     FT_UNUSED( module );
259 
260     return ft_service_list_lookup( otvalid_services, service_id );
261   }
262 
263 
264   FT_CALLBACK_TABLE_DEF
265   const FT_Module_Class  otv_module_class =
266   {
267     0,
268     sizeof ( FT_ModuleRec ),
269     "otvalid",
270     0x10000L,
271     0x20000L,
272 
273     NULL,              /* module-specific interface */
274 
275     (FT_Module_Constructor)NULL,                /* module_init   */
276     (FT_Module_Destructor) NULL,                /* module_done   */
277     (FT_Module_Requester)  otvalid_get_service  /* get_interface */
278   };
279 
280 
281 /* END */
282