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