ReactOS  0.4.14-dev-49-gfb4591c
t1parse.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* t1parse.c */
4 /* */
5 /* Type 1 parser (body). */
6 /* */
7 /* Copyright 1996-2018 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 trace_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
71  FT_UShort *atag,
72  FT_ULong *asize )
73  {
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
99  const char* header_string,
100  size_t header_length )
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 
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 )
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 
262  PSAux_Service psaux )
263  {
264  FT_Stream stream = parser->stream;
265  FT_Memory memory = parser->root.memory;
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 
387  if ( parser->root.error )
388  break;
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 
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 */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:303
T1_Finalize_Parser(T1_Parser parser)
Definition: t1parse.c:244
int FT_Error
Definition: fttypes.h:300
unsigned long FT_ULong
Definition: fttypes.h:253
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define error(str)
Definition: mkdosfs.c:1605
T1_New_Parser(T1_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux)
Definition: t1parse.c:136
static FT_Error check_type1_format(FT_Stream stream, const char *header_string, size_t header_length)
Definition: t1parse.c:98
#define T1_Skip_Spaces(p)
Definition: t1parse.h:88
#define ft_memchr
Definition: ftstdlib.h:80
#define U(x)
Definition: wordpad.c:44
Definition: ecma_167.h:138
#define ft_isxdigit(x)
Definition: ftobjs.h:120
return FT_Err_Ok
Definition: ftbbox.c:511
static char memory[1024 *256]
Definition: process.c:116
#define FT_READ_USHORT(var)
Definition: ftstream.h:309
GLint limit
Definition: glext.h:10326
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:154
#define FT_THROW(e)
Definition: ftdebug.h:213
smooth NULL
Definition: ftsmooth.c:416
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:493
return Found
Definition: dirsup.c:1270
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:388
GLsizeiptr size
Definition: glext.h:5919
#define T1_Skip_PS_Token(p)
Definition: t1parse.h:89
if(!(yy_init))
Definition: macro.lex.yy.c:714
static FT_Error read_pfb_tag(FT_Stream stream, FT_UShort *atag, FT_ULong *asize)
Definition: t1parse.c:70
static void Exit(void)
Definition: sock.c:1331
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
unsigned int error
Definition: inffile.c:97
#define FT_READ_ULONG_LE(var)
Definition: ftstream.h:318
#define FT_ERR_NEQ(x, e)
Definition: fttypes.h:593
static const WCHAR L[]
Definition: oid.c:1250
unsigned int size
Definition: parse.h:27
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
T1_Get_Private_Dict(T1_Parser parser, PSAux_Service psaux)
Definition: t1parse.c:261
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
GLenum GLsizei len
Definition: glext.h:6722
#define FT_BOOL(x)
Definition: fttypes.h:578
#define FT_FRAME_EXIT()
Definition: ftstream.h:517
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
Definition: hiveinit.c:368
ULARGE_INTEGER pos
Definition: request.c:4080
#define FT_STREAM_POS()
Definition: ftstream.h:486
#define ft_memcmp
Definition: ftstdlib.h:81
unsigned char dummy
Definition: maze.c:118
Definition: import.c:86
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:512
FT_BEGIN_HEADER struct T1_ParserRec_ * T1_Parser
unsigned short FT_UShort
Definition: fttypes.h:209
#define FT_MEM_MOVE(dest, source, count)
Definition: ftmemory.h:231
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:497
char * tag
Definition: main.c:59