Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /***************************************************************************/ |
2 | /* */ |
||
3 | /* gxvfeat.c */ |
||
4 | /* */ |
||
5 | /* TrueTypeGX/AAT feat table validation (body). */ |
||
6 | /* */ |
||
7 | /* Copyright 2004, 2005, 2008, 2012 by */ |
||
8 | /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ |
||
9 | /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
||
10 | /* */ |
||
11 | /* This file is part of the FreeType project, and may only be used, */ |
||
12 | /* modified, and distributed under the terms of the FreeType project */ |
||
13 | /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
||
14 | /* this file you indicate that you have read the license and */ |
||
15 | /* understand and accept it fully. */ |
||
16 | /* */ |
||
17 | /***************************************************************************/ |
||
18 | |||
19 | /***************************************************************************/ |
||
20 | /* */ |
||
21 | /* gxvalid is derived from both gxlayout module and otvalid module. */ |
||
22 | /* Development of gxlayout is supported by the Information-technology */ |
||
23 | /* Promotion Agency(IPA), Japan. */ |
||
24 | /* */ |
||
25 | /***************************************************************************/ |
||
26 | |||
27 | |||
28 | #include "gxvalid.h" |
||
29 | #include "gxvcommn.h" |
||
30 | #include "gxvfeat.h" |
||
31 | |||
32 | |||
33 | /*************************************************************************/ |
||
34 | /* */ |
||
35 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||
36 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||
37 | /* messages during execution. */ |
||
38 | /* */ |
||
39 | #undef FT_COMPONENT |
||
40 | #define FT_COMPONENT trace_gxvfeat |
||
41 | |||
42 | |||
43 | /*************************************************************************/ |
||
44 | /*************************************************************************/ |
||
45 | /***** *****/ |
||
46 | /***** Data and Types *****/ |
||
47 | /***** *****/ |
||
48 | /*************************************************************************/ |
||
49 | /*************************************************************************/ |
||
50 | |||
51 | typedef struct GXV_feat_DataRec_ |
||
52 | { |
||
53 | FT_UInt reserved_size; |
||
54 | FT_UShort feature; |
||
55 | FT_UShort setting; |
||
56 | |||
57 | } GXV_feat_DataRec, *GXV_feat_Data; |
||
58 | |||
59 | |||
60 | #define GXV_FEAT_DATA( field ) GXV_TABLE_DATA( feat, field ) |
||
61 | |||
62 | |||
63 | typedef enum GXV_FeatureFlagsMask_ |
||
64 | { |
||
65 | GXV_FEAT_MASK_EXCLUSIVE_SETTINGS = 0x8000U, |
||
66 | GXV_FEAT_MASK_DYNAMIC_DEFAULT = 0x4000, |
||
67 | GXV_FEAT_MASK_UNUSED = 0x3F00, |
||
68 | GXV_FEAT_MASK_DEFAULT_SETTING = 0x00FF |
||
69 | |||
70 | } GXV_FeatureFlagsMask; |
||
71 | |||
72 | |||
73 | /*************************************************************************/ |
||
74 | /*************************************************************************/ |
||
75 | /***** *****/ |
||
76 | /***** UTILITY FUNCTIONS *****/ |
||
77 | /***** *****/ |
||
78 | /*************************************************************************/ |
||
79 | /*************************************************************************/ |
||
80 | |||
81 | static void |
||
82 | gxv_feat_registry_validate( FT_UShort feature, |
||
83 | FT_UShort nSettings, |
||
84 | FT_Bool exclusive, |
||
85 | GXV_Validator valid ) |
||
86 | { |
||
87 | GXV_NAME_ENTER( "feature in registry" ); |
||
88 | |||
89 | GXV_TRACE(( " (feature = %u)\n", feature )); |
||
90 | |||
91 | if ( feature >= gxv_feat_registry_length ) |
||
92 | { |
||
93 | GXV_TRACE(( "feature number %d is out of range %d\n", |
||
94 | feature, gxv_feat_registry_length )); |
||
95 | GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); |
||
96 | goto Exit; |
||
97 | } |
||
98 | |||
99 | if ( gxv_feat_registry[feature].existence == 0 ) |
||
100 | { |
||
101 | GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n", |
||
102 | feature )); |
||
103 | GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); |
||
104 | goto Exit; |
||
105 | } |
||
106 | |||
107 | if ( gxv_feat_registry[feature].apple_reserved ) |
||
108 | { |
||
109 | /* Don't use here. Apple is reserved. */ |
||
110 | GXV_TRACE(( "feature number %d is reserved by Apple\n", feature )); |
||
111 | if ( valid->root->level >= FT_VALIDATE_TIGHT ) |
||
112 | FT_INVALID_DATA; |
||
113 | } |
||
114 | |||
115 | if ( nSettings != gxv_feat_registry[feature].nSettings ) |
||
116 | { |
||
117 | GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n", |
||
118 | feature, nSettings, |
||
119 | gxv_feat_registry[feature].nSettings )); |
||
120 | if ( valid->root->level >= FT_VALIDATE_TIGHT ) |
||
121 | FT_INVALID_DATA; |
||
122 | } |
||
123 | |||
124 | if ( exclusive != gxv_feat_registry[feature].exclusive ) |
||
125 | { |
||
126 | GXV_TRACE(( "exclusive flag %d differs from predefined value\n", |
||
127 | exclusive )); |
||
128 | if ( valid->root->level >= FT_VALIDATE_TIGHT ) |
||
129 | FT_INVALID_DATA; |
||
130 | } |
||
131 | |||
132 | Exit: |
||
133 | GXV_EXIT; |
||
134 | } |
||
135 | |||
136 | |||
137 | static void |
||
138 | gxv_feat_name_index_validate( FT_Bytes table, |
||
139 | FT_Bytes limit, |
||
140 | GXV_Validator valid ) |
||
141 | { |
||
142 | FT_Bytes p = table; |
||
143 | |||
144 | FT_Short nameIndex; |
||
145 | |||
146 | |||
147 | GXV_NAME_ENTER( "nameIndex" ); |
||
148 | |||
149 | GXV_LIMIT_CHECK( 2 ); |
||
150 | nameIndex = FT_NEXT_SHORT ( p ); |
||
151 | GXV_TRACE(( " (nameIndex = %d)\n", nameIndex )); |
||
152 | |||
153 | gxv_sfntName_validate( (FT_UShort)nameIndex, |
||
154 | 255, |
||
155 | 32768U, |
||
156 | valid ); |
||
157 | |||
158 | GXV_EXIT; |
||
159 | } |
||
160 | |||
161 | |||
162 | static void |
||
163 | gxv_feat_setting_validate( FT_Bytes table, |
||
164 | FT_Bytes limit, |
||
165 | FT_Bool exclusive, |
||
166 | GXV_Validator valid ) |
||
167 | { |
||
168 | FT_Bytes p = table; |
||
169 | FT_UShort setting; |
||
170 | |||
171 | |||
172 | GXV_NAME_ENTER( "setting" ); |
||
173 | |||
174 | GXV_LIMIT_CHECK( 2 ); |
||
175 | |||
176 | setting = FT_NEXT_USHORT( p ); |
||
177 | |||
178 | /* If we have exclusive setting, the setting should be odd. */ |
||
179 | if ( exclusive && ( setting & 1 ) == 0 ) |
||
180 | FT_INVALID_DATA; |
||
181 | |||
182 | gxv_feat_name_index_validate( p, limit, valid ); |
||
183 | |||
184 | GXV_FEAT_DATA( setting ) = setting; |
||
185 | |||
186 | GXV_EXIT; |
||
187 | } |
||
188 | |||
189 | |||
190 | static void |
||
191 | gxv_feat_name_validate( FT_Bytes table, |
||
192 | FT_Bytes limit, |
||
193 | GXV_Validator valid ) |
||
194 | { |
||
195 | FT_Bytes p = table; |
||
196 | FT_UInt reserved_size = GXV_FEAT_DATA( reserved_size ); |
||
197 | |||
198 | FT_UShort feature; |
||
199 | FT_UShort nSettings; |
||
200 | FT_ULong settingTable; |
||
201 | FT_UShort featureFlags; |
||
202 | |||
203 | FT_Bool exclusive; |
||
204 | FT_Int last_setting; |
||
205 | FT_UInt i; |
||
206 | |||
207 | |||
208 | GXV_NAME_ENTER( "name" ); |
||
209 | |||
210 | /* feature + nSettings + settingTable + featureFlags */ |
||
211 | GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 ); |
||
212 | |||
213 | feature = FT_NEXT_USHORT( p ); |
||
214 | GXV_FEAT_DATA( feature ) = feature; |
||
215 | |||
216 | nSettings = FT_NEXT_USHORT( p ); |
||
217 | settingTable = FT_NEXT_ULONG ( p ); |
||
218 | featureFlags = FT_NEXT_USHORT( p ); |
||
219 | |||
220 | if ( settingTable < reserved_size ) |
||
221 | FT_INVALID_OFFSET; |
||
222 | |||
223 | if ( ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 ) |
||
224 | GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); |
||
225 | |||
226 | exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS ); |
||
227 | if ( exclusive ) |
||
228 | { |
||
229 | FT_Byte dynamic_default; |
||
230 | |||
231 | |||
232 | if ( featureFlags & GXV_FEAT_MASK_DYNAMIC_DEFAULT ) |
||
233 | dynamic_default = (FT_Byte)( featureFlags & |
||
234 | GXV_FEAT_MASK_DEFAULT_SETTING ); |
||
235 | else |
||
236 | dynamic_default = 0; |
||
237 | |||
238 | /* If exclusive, check whether default setting is in the range. */ |
||
239 | if ( !( dynamic_default < nSettings ) ) |
||
240 | FT_INVALID_FORMAT; |
||
241 | } |
||
242 | |||
243 | gxv_feat_registry_validate( feature, nSettings, exclusive, valid ); |
||
244 | |||
245 | gxv_feat_name_index_validate( p, limit, valid ); |
||
246 | |||
247 | p = valid->root->base + settingTable; |
||
248 | for ( last_setting = -1, i = 0; i < nSettings; i++ ) |
||
249 | { |
||
250 | gxv_feat_setting_validate( p, limit, exclusive, valid ); |
||
251 | |||
252 | if ( (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting ) |
||
253 | GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT ); |
||
254 | |||
255 | last_setting = (FT_Int)GXV_FEAT_DATA( setting ); |
||
256 | /* setting + nameIndex */ |
||
257 | p += ( 2 + 2 ); |
||
258 | } |
||
259 | |||
260 | GXV_EXIT; |
||
261 | } |
||
262 | |||
263 | |||
264 | /*************************************************************************/ |
||
265 | /*************************************************************************/ |
||
266 | /***** *****/ |
||
267 | /***** feat TABLE *****/ |
||
268 | /***** *****/ |
||
269 | /*************************************************************************/ |
||
270 | /*************************************************************************/ |
||
271 | |||
272 | FT_LOCAL_DEF( void ) |
||
273 | gxv_feat_validate( FT_Bytes table, |
||
274 | FT_Face face, |
||
275 | FT_Validator ftvalid ) |
||
276 | { |
||
277 | GXV_ValidatorRec validrec; |
||
278 | GXV_Validator valid = &validrec; |
||
279 | |||
280 | GXV_feat_DataRec featrec; |
||
281 | GXV_feat_Data feat = &featrec; |
||
282 | |||
283 | FT_Bytes p = table; |
||
284 | FT_Bytes limit = 0; |
||
285 | |||
286 | FT_UInt featureNameCount; |
||
287 | |||
288 | FT_UInt i; |
||
289 | FT_Int last_feature; |
||
290 | |||
291 | |||
292 | valid->root = ftvalid; |
||
293 | valid->table_data = feat; |
||
294 | valid->face = face; |
||
295 | |||
296 | FT_TRACE3(( "validating `feat' table\n" )); |
||
297 | GXV_INIT; |
||
298 | |||
299 | feat->reserved_size = 0; |
||
300 | |||
301 | /* version + featureNameCount + none_0 + none_1 */ |
||
302 | GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 ); |
||
303 | feat->reserved_size += 4 + 2 + 2 + 4; |
||
304 | |||
305 | if ( FT_NEXT_ULONG( p ) != 0x00010000UL ) /* Version */ |
||
306 | FT_INVALID_FORMAT; |
||
307 | |||
308 | featureNameCount = FT_NEXT_USHORT( p ); |
||
309 | GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount )); |
||
310 | |||
311 | if ( !( IS_PARANOID_VALIDATION ) ) |
||
312 | p += 6; /* skip (none) and (none) */ |
||
313 | else |
||
314 | { |
||
315 | if ( FT_NEXT_USHORT( p ) != 0 ) |
||
316 | FT_INVALID_DATA; |
||
317 | |||
318 | if ( FT_NEXT_ULONG( p ) != 0 ) |
||
319 | FT_INVALID_DATA; |
||
320 | } |
||
321 | |||
322 | feat->reserved_size += featureNameCount * ( 2 + 2 + 4 + 2 + 2 ); |
||
323 | |||
324 | for ( last_feature = -1, i = 0; i < featureNameCount; i++ ) |
||
325 | { |
||
326 | gxv_feat_name_validate( p, limit, valid ); |
||
327 | |||
328 | if ( (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature ) |
||
329 | GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT ); |
||
330 | |||
331 | last_feature = GXV_FEAT_DATA( feature ); |
||
332 | p += 2 + 2 + 4 + 2 + 2; |
||
333 | } |
||
334 | |||
335 | FT_TRACE4(( "\n" )); |
||
336 | } |
||
337 | |||
338 | |||
339 | /* END */=>>=>>>> |