1 | /**************************************************************************** |
2 | * |
3 | * t1parse.c |
4 | * |
5 | * Type 1 parser (body). |
6 | * |
7 | * Copyright (C) 1996-2019 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 | /************************************************************************** |
20 | * |
21 | * The Type 1 parser is in charge of the following: |
22 | * |
23 | * - provide an implementation of a growing sequence of objects called |
24 | * a `T1_Table' (used to build various tables needed by the loader). |
25 | * |
26 | * - opening .pfb and .pfa files to extract their top-level and private |
27 | * dictionaries. |
28 | * |
29 | * - read numbers, arrays & strings from any dictionary. |
30 | * |
31 | * See `t1load.c' to see how data is loaded from the font file. |
32 | * |
33 | */ |
34 | |
35 | |
36 | #include <ft2build.h> |
37 | #include FT_INTERNAL_DEBUG_H |
38 | #include FT_INTERNAL_STREAM_H |
39 | #include FT_INTERNAL_POSTSCRIPT_AUX_H |
40 | |
41 | #include "t1parse.h" |
42 | |
43 | #include "t1errors.h" |
44 | |
45 | |
46 | /************************************************************************** |
47 | * |
48 | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
49 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
50 | * messages during execution. |
51 | */ |
52 | #undef FT_COMPONENT |
53 | #define FT_COMPONENT t1parse |
54 | |
55 | |
56 | /*************************************************************************/ |
57 | /*************************************************************************/ |
58 | /*************************************************************************/ |
59 | /***** *****/ |
60 | /***** INPUT STREAM PARSER *****/ |
61 | /***** *****/ |
62 | /*************************************************************************/ |
63 | /*************************************************************************/ |
64 | /*************************************************************************/ |
65 | |
66 | |
67 | /* see Adobe Technical Note 5040.Download_Fonts.pdf */ |
68 | |
69 | static FT_Error |
70 | read_pfb_tag( FT_Stream stream, |
71 | FT_UShort *atag, |
72 | FT_ULong *asize ) |
73 | { |
74 | FT_Error error; |
75 | FT_UShort tag; |
76 | FT_ULong size; |
77 | |
78 | |
79 | *atag = 0; |
80 | *asize = 0; |
81 | |
82 | if ( !FT_READ_USHORT( tag ) ) |
83 | { |
84 | if ( tag == 0x8001U || tag == 0x8002U ) |
85 | { |
86 | if ( !FT_READ_ULONG_LE( size ) ) |
87 | *asize = size; |
88 | } |
89 | |
90 | *atag = tag; |
91 | } |
92 | |
93 | return error; |
94 | } |
95 | |
96 | |
97 | static FT_Error |
98 | check_type1_format( FT_Stream stream, |
99 | const char* , |
100 | size_t ) |
101 | { |
102 | FT_Error error; |
103 | FT_UShort tag; |
104 | FT_ULong dummy; |
105 | |
106 | |
107 | if ( FT_STREAM_SEEK( 0 ) ) |
108 | goto Exit; |
109 | |
110 | error = read_pfb_tag( stream, &tag, &dummy ); |
111 | if ( error ) |
112 | goto Exit; |
113 | |
114 | /* We assume that the first segment in a PFB is always encoded as */ |
115 | /* text. This might be wrong (and the specification doesn't insist */ |
116 | /* on that), but we have never seen a counterexample. */ |
117 | if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) ) |
118 | goto Exit; |
119 | |
120 | if ( !FT_FRAME_ENTER( header_length ) ) |
121 | { |
122 | error = FT_Err_Ok; |
123 | |
124 | if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 ) |
125 | error = FT_THROW( Unknown_File_Format ); |
126 | |
127 | FT_FRAME_EXIT(); |
128 | } |
129 | |
130 | Exit: |
131 | return error; |
132 | } |
133 | |
134 | |
135 | FT_LOCAL_DEF( FT_Error ) |
136 | T1_New_Parser( T1_Parser parser, |
137 | FT_Stream stream, |
138 | FT_Memory memory, |
139 | PSAux_Service psaux ) |
140 | { |
141 | FT_Error error; |
142 | FT_UShort tag; |
143 | FT_ULong size; |
144 | |
145 | |
146 | psaux->ps_parser_funcs->init( &parser->root, NULL, NULL, memory ); |
147 | |
148 | parser->stream = stream; |
149 | parser->base_len = 0; |
150 | parser->base_dict = NULL; |
151 | parser->private_len = 0; |
152 | parser->private_dict = NULL; |
153 | parser->in_pfb = 0; |
154 | parser->in_memory = 0; |
155 | parser->single_block = 0; |
156 | |
157 | /* check the header format */ |
158 | error = check_type1_format( stream, "%!PS-AdobeFont" , 14 ); |
159 | if ( error ) |
160 | { |
161 | if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) |
162 | goto Exit; |
163 | |
164 | error = check_type1_format( stream, "%!FontType" , 10 ); |
165 | if ( error ) |
166 | { |
167 | FT_TRACE2(( " not a Type 1 font\n" )); |
168 | goto Exit; |
169 | } |
170 | } |
171 | |
172 | /******************************************************************* |
173 | * |
174 | * Here a short summary of what is going on: |
175 | * |
176 | * When creating a new Type 1 parser, we try to locate and load |
177 | * the base dictionary if this is possible (i.e., for PFB |
178 | * files). Otherwise, we load the whole font into memory. |
179 | * |
180 | * When `loading' the base dictionary, we only setup pointers |
181 | * in the case of a memory-based stream. Otherwise, we |
182 | * allocate and load the base dictionary in it. |
183 | * |
184 | * parser->in_pfb is set if we are in a binary (`.pfb') font. |
185 | * parser->in_memory is set if we have a memory stream. |
186 | */ |
187 | |
188 | /* try to compute the size of the base dictionary; */ |
189 | /* look for a Postscript binary file tag, i.e., 0x8001 */ |
190 | if ( FT_STREAM_SEEK( 0L ) ) |
191 | goto Exit; |
192 | |
193 | error = read_pfb_tag( stream, &tag, &size ); |
194 | if ( error ) |
195 | goto Exit; |
196 | |
197 | if ( tag != 0x8001U ) |
198 | { |
199 | /* assume that this is a PFA file for now; an error will */ |
200 | /* be produced later when more things are checked */ |
201 | if ( FT_STREAM_SEEK( 0L ) ) |
202 | goto Exit; |
203 | size = stream->size; |
204 | } |
205 | else |
206 | parser->in_pfb = 1; |
207 | |
208 | /* now, try to load `size' bytes of the `base' dictionary we */ |
209 | /* found previously */ |
210 | |
211 | /* if it is a memory-based resource, set up pointers */ |
212 | if ( !stream->read ) |
213 | { |
214 | parser->base_dict = (FT_Byte*)stream->base + stream->pos; |
215 | parser->base_len = size; |
216 | parser->in_memory = 1; |
217 | |
218 | /* check that the `size' field is valid */ |
219 | if ( FT_STREAM_SKIP( size ) ) |
220 | goto Exit; |
221 | } |
222 | else |
223 | { |
224 | /* read segment in memory -- this is clumsy, but so does the format */ |
225 | if ( FT_ALLOC( parser->base_dict, size ) || |
226 | FT_STREAM_READ( parser->base_dict, size ) ) |
227 | goto Exit; |
228 | parser->base_len = size; |
229 | } |
230 | |
231 | parser->root.base = parser->base_dict; |
232 | parser->root.cursor = parser->base_dict; |
233 | parser->root.limit = parser->root.cursor + parser->base_len; |
234 | |
235 | Exit: |
236 | if ( error && !parser->in_memory ) |
237 | FT_FREE( parser->base_dict ); |
238 | |
239 | return error; |
240 | } |
241 | |
242 | |
243 | FT_LOCAL_DEF( void ) |
244 | T1_Finalize_Parser( T1_Parser parser ) |
245 | { |
246 | FT_Memory memory = parser->root.memory; |
247 | |
248 | |
249 | /* always free the private dictionary */ |
250 | FT_FREE( parser->private_dict ); |
251 | |
252 | /* free the base dictionary only when we have a disk stream */ |
253 | if ( !parser->in_memory ) |
254 | FT_FREE( parser->base_dict ); |
255 | |
256 | parser->root.funcs.done( &parser->root ); |
257 | } |
258 | |
259 | |
260 | FT_LOCAL_DEF( FT_Error ) |
261 | T1_Get_Private_Dict( T1_Parser parser, |
262 | PSAux_Service psaux ) |
263 | { |
264 | FT_Stream stream = parser->stream; |
265 | FT_Memory memory = parser->root.memory; |
266 | FT_Error error = FT_Err_Ok; |
267 | FT_ULong size; |
268 | |
269 | |
270 | if ( parser->in_pfb ) |
271 | { |
272 | /* in the case of the PFB format, the private dictionary can be */ |
273 | /* made of several segments. We thus first read the number of */ |
274 | /* segments to compute the total size of the private dictionary */ |
275 | /* then re-read them into memory. */ |
276 | FT_ULong start_pos = FT_STREAM_POS(); |
277 | FT_UShort tag; |
278 | |
279 | |
280 | parser->private_len = 0; |
281 | for (;;) |
282 | { |
283 | error = read_pfb_tag( stream, &tag, &size ); |
284 | if ( error ) |
285 | goto Fail; |
286 | |
287 | if ( tag != 0x8002U ) |
288 | break; |
289 | |
290 | parser->private_len += size; |
291 | |
292 | if ( FT_STREAM_SKIP( size ) ) |
293 | goto Fail; |
294 | } |
295 | |
296 | /* Check that we have a private dictionary there */ |
297 | /* and allocate private dictionary buffer */ |
298 | if ( parser->private_len == 0 ) |
299 | { |
300 | FT_ERROR(( "T1_Get_Private_Dict:" |
301 | " invalid private dictionary section\n" )); |
302 | error = FT_THROW( Invalid_File_Format ); |
303 | goto Fail; |
304 | } |
305 | |
306 | if ( FT_STREAM_SEEK( start_pos ) || |
307 | FT_ALLOC( parser->private_dict, parser->private_len ) ) |
308 | goto Fail; |
309 | |
310 | parser->private_len = 0; |
311 | for (;;) |
312 | { |
313 | error = read_pfb_tag( stream, &tag, &size ); |
314 | if ( error || tag != 0x8002U ) |
315 | { |
316 | error = FT_Err_Ok; |
317 | break; |
318 | } |
319 | |
320 | if ( FT_STREAM_READ( parser->private_dict + parser->private_len, |
321 | size ) ) |
322 | goto Fail; |
323 | |
324 | parser->private_len += size; |
325 | } |
326 | } |
327 | else |
328 | { |
329 | /* We have already `loaded' the whole PFA font file into memory; */ |
330 | /* if this is a memory resource, allocate a new block to hold */ |
331 | /* the private dict. Otherwise, simply overwrite into the base */ |
332 | /* dictionary block in the heap. */ |
333 | |
334 | /* first of all, look at the `eexec' keyword */ |
335 | FT_Byte* cur = parser->base_dict; |
336 | FT_Byte* limit = cur + parser->base_len; |
337 | FT_Pointer pos_lf; |
338 | FT_Bool test_cr; |
339 | |
340 | |
341 | Again: |
342 | for (;;) |
343 | { |
344 | if ( cur[0] == 'e' && |
345 | cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ |
346 | /* whitespace + 4 chars */ |
347 | { |
348 | if ( cur[1] == 'e' && |
349 | cur[2] == 'x' && |
350 | cur[3] == 'e' && |
351 | cur[4] == 'c' ) |
352 | break; |
353 | } |
354 | cur++; |
355 | if ( cur >= limit ) |
356 | { |
357 | FT_ERROR(( "T1_Get_Private_Dict:" |
358 | " could not find `eexec' keyword\n" )); |
359 | error = FT_THROW( Invalid_File_Format ); |
360 | goto Exit; |
361 | } |
362 | } |
363 | |
364 | /* check whether `eexec' was real -- it could be in a comment */ |
365 | /* or string (as e.g. in u003043t.gsf from ghostscript) */ |
366 | |
367 | parser->root.cursor = parser->base_dict; |
368 | /* set limit to `eexec' + whitespace + 4 characters */ |
369 | parser->root.limit = cur + 10; |
370 | |
371 | cur = parser->root.cursor; |
372 | limit = parser->root.limit; |
373 | |
374 | while ( cur < limit ) |
375 | { |
376 | if ( cur[0] == 'e' && |
377 | cur + 5 < limit ) |
378 | { |
379 | if ( cur[1] == 'e' && |
380 | cur[2] == 'x' && |
381 | cur[3] == 'e' && |
382 | cur[4] == 'c' ) |
383 | goto Found; |
384 | } |
385 | |
386 | T1_Skip_PS_Token( parser ); |
387 | if ( parser->root.error ) |
388 | break; |
389 | T1_Skip_Spaces ( parser ); |
390 | cur = parser->root.cursor; |
391 | } |
392 | |
393 | /* we haven't found the correct `eexec'; go back and continue */ |
394 | /* searching */ |
395 | |
396 | cur = limit; |
397 | limit = parser->base_dict + parser->base_len; |
398 | |
399 | if ( cur >= limit ) |
400 | { |
401 | FT_ERROR(( "T1_Get_Private_Dict:" |
402 | " premature end in private dictionary\n" )); |
403 | error = FT_THROW( Invalid_File_Format ); |
404 | goto Exit; |
405 | } |
406 | |
407 | goto Again; |
408 | |
409 | /* now determine where to write the _encrypted_ binary private */ |
410 | /* dictionary. We overwrite the base dictionary for disk-based */ |
411 | /* resources and allocate a new block otherwise */ |
412 | |
413 | Found: |
414 | parser->root.limit = parser->base_dict + parser->base_len; |
415 | |
416 | T1_Skip_PS_Token( parser ); |
417 | cur = parser->root.cursor; |
418 | limit = parser->root.limit; |
419 | |
420 | /* According to the Type 1 spec, the first cipher byte must not be */ |
421 | /* an ASCII whitespace character code (blank, tab, carriage return */ |
422 | /* or line feed). We have seen Type 1 fonts with two line feed */ |
423 | /* characters... So skip now all whitespace character codes. */ |
424 | /* */ |
425 | /* On the other hand, Adobe's Type 1 parser handles fonts just */ |
426 | /* fine that are violating this limitation, so we add a heuristic */ |
427 | /* test to stop at \r only if it is not used for EOL. */ |
428 | |
429 | pos_lf = ft_memchr( cur, '\n', (size_t)( limit - cur ) ); |
430 | test_cr = FT_BOOL( !pos_lf || |
431 | pos_lf > ft_memchr( cur, |
432 | '\r', |
433 | (size_t)( limit - cur ) ) ); |
434 | |
435 | while ( cur < limit && |
436 | ( *cur == ' ' || |
437 | *cur == '\t' || |
438 | (test_cr && *cur == '\r' ) || |
439 | *cur == '\n' ) ) |
440 | cur++; |
441 | if ( cur >= limit ) |
442 | { |
443 | FT_ERROR(( "T1_Get_Private_Dict:" |
444 | " `eexec' not properly terminated\n" )); |
445 | error = FT_THROW( Invalid_File_Format ); |
446 | goto Exit; |
447 | } |
448 | |
449 | size = parser->base_len - (FT_ULong)( cur - parser->base_dict ); |
450 | |
451 | if ( parser->in_memory ) |
452 | { |
453 | /* note that we allocate one more byte to put a terminating `0' */ |
454 | if ( FT_ALLOC( parser->private_dict, size + 1 ) ) |
455 | goto Fail; |
456 | parser->private_len = size; |
457 | } |
458 | else |
459 | { |
460 | parser->single_block = 1; |
461 | parser->private_dict = parser->base_dict; |
462 | parser->private_len = size; |
463 | parser->base_dict = NULL; |
464 | parser->base_len = 0; |
465 | } |
466 | |
467 | /* now determine whether the private dictionary is encoded in binary */ |
468 | /* or hexadecimal ASCII format -- decode it accordingly */ |
469 | |
470 | /* we need to access the next 4 bytes (after the final whitespace */ |
471 | /* following the `eexec' keyword); if they all are hexadecimal */ |
472 | /* digits, then we have a case of ASCII storage */ |
473 | |
474 | if ( cur + 3 < limit && |
475 | ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && |
476 | ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) |
477 | { |
478 | /* ASCII hexadecimal encoding */ |
479 | FT_ULong len; |
480 | |
481 | |
482 | parser->root.cursor = cur; |
483 | (void)psaux->ps_parser_funcs->to_bytes( &parser->root, |
484 | parser->private_dict, |
485 | parser->private_len, |
486 | &len, |
487 | 0 ); |
488 | parser->private_len = len; |
489 | |
490 | /* put a safeguard */ |
491 | parser->private_dict[len] = '\0'; |
492 | } |
493 | else |
494 | /* binary encoding -- copy the private dict */ |
495 | FT_MEM_MOVE( parser->private_dict, cur, size ); |
496 | } |
497 | |
498 | /* we now decrypt the encoded binary private dictionary */ |
499 | psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); |
500 | |
501 | if ( parser->private_len < 4 ) |
502 | { |
503 | FT_ERROR(( "T1_Get_Private_Dict:" |
504 | " invalid private dictionary section\n" )); |
505 | error = FT_THROW( Invalid_File_Format ); |
506 | goto Fail; |
507 | } |
508 | |
509 | /* replace the four random bytes at the beginning with whitespace */ |
510 | parser->private_dict[0] = ' '; |
511 | parser->private_dict[1] = ' '; |
512 | parser->private_dict[2] = ' '; |
513 | parser->private_dict[3] = ' '; |
514 | |
515 | parser->root.base = parser->private_dict; |
516 | parser->root.cursor = parser->private_dict; |
517 | parser->root.limit = parser->root.cursor + parser->private_len; |
518 | |
519 | Fail: |
520 | Exit: |
521 | return error; |
522 | } |
523 | |
524 | |
525 | /* END */ |
526 | |