text: /****************************************************************************
   *
   * gxvcommn.h
   *
   *   TrueTypeGX/AAT common tables validation (specification).
   *
   * Copyright (C) 2004-2021 by
   * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
   * David Turner, Robert Wilhelm, and Werner Lemberg.
   *
   * This file is part of the FreeType project, and may only be used,
   * modified, and distributed under the terms of the FreeType project
   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
   * this file you indicate that you have read the license and
   * understand and accept it fully.
   *
   */
  
  /****************************************************************************
   *
   * gxvalid is derived from both gxlayout module and otvalid module.
   * Development of gxlayout is supported by the Information-technology
   * Promotion Agency(IPA), Japan.
   *
   */
  
  
    /*
     * keywords in variable naming
     * ---------------------------
     * table:  Of type FT_Bytes, pointing to the start of this table/subtable.
     * limit:  Of type FT_Bytes, pointing to the end of this table/subtable,
     *         including padding for alignment.
     * offset: Of type FT_UInt, the number of octets from the start to target.
     * length: Of type FT_UInt, the number of octets from the start to the
     *         end in this table/subtable, including padding for alignment.
     *
     *  _MIN, _MAX: Should be added to the tail of macros, as INT_MIN, etc.
     */
  
  
  #ifndef GXVCOMMN_H_
  #define GXVCOMMN_H_
  
  
  #include "gxvalid.h"
  #include <freetype/internal/ftdebug.h>
  #include <freetype/ftsnames.h>
  
  
  FT_BEGIN_HEADER
  
  
    /* some variables are not evaluated or only used in trace */
  
  #ifdef  FT_DEBUG_LEVEL_TRACE
  #define GXV_LOAD_TRACE_VARS
  #else
  #undef  GXV_LOAD_TRACE_VARS
  #endif
  
  #undef GXV_LOAD_UNUSED_VARS /* debug purpose */
  
  #define IS_PARANOID_VALIDATION                             \
            ( gxvalid->root->level >= FT_VALIDATE_PARANOID )
  #define GXV_SET_ERR_IF_PARANOID( err )                              \
            do { if ( IS_PARANOID_VALIDATION ) ( err ); } while ( 0 )
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                         VALIDATION                            *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    typedef struct GXV_ValidatorRec_*  GXV_Validator;
  
  
  #define DUMMY_LIMIT 0
  
    typedef void
    (*GXV_Validate_Func)( FT_Bytes       table,
                          FT_Bytes       limit,
                          GXV_Validator  gxvalid );
  
  
    /* ====================== LookupTable Validator ======================== */
  
    typedef union  GXV_LookupValueDesc_
    {
      FT_UShort u;
      FT_Short  s;
  
    } GXV_LookupValueDesc;
  
    typedef const GXV_LookupValueDesc* GXV_LookupValueCPtr;
  
    typedef enum  GXV_LookupValue_SignSpec_
    {
      GXV_LOOKUPVALUE_UNSIGNED = 0,
      GXV_LOOKUPVALUE_SIGNED
  
    } GXV_LookupValue_SignSpec;
  
  
    typedef void
    (*GXV_Lookup_Value_Validate_Func)( FT_UShort            glyph,
                                       GXV_LookupValueCPtr  value_p,
                                       GXV_Validator        gxvalid );
  
    typedef GXV_LookupValueDesc
    (*GXV_Lookup_Fmt4_Transit_Func)( FT_UShort            relative_gindex,
                                     GXV_LookupValueCPtr  base_value_p,
                                     FT_Bytes             lookuptbl_limit,
                                     GXV_Validator        gxvalid );
  
  
    /* ====================== StateTable Validator ========================= */
  
    typedef enum  GXV_GlyphOffset_Format_
    {
      GXV_GLYPHOFFSET_NONE   = -1,
      GXV_GLYPHOFFSET_UCHAR  = 2,
      GXV_GLYPHOFFSET_CHAR,
      GXV_GLYPHOFFSET_USHORT = 4,
      GXV_GLYPHOFFSET_SHORT,
      GXV_GLYPHOFFSET_ULONG  = 8,
      GXV_GLYPHOFFSET_LONG
  
    } GXV_GlyphOffset_Format;
  
  
  #define GXV_GLYPHOFFSET_FMT( table )           \
          ( gxvalid->table.entry_glyphoffset_fmt )
  
  #define GXV_GLYPHOFFSET_SIZE( table )              \
          ( gxvalid->table.entry_glyphoffset_fmt / 2 )
  
  
    /* ----------------------- 16bit StateTable ---------------------------- */
  
    typedef union  GXV_StateTable_GlyphOffsetDesc_
    {
      FT_Byte    uc;
      FT_UShort  u;       /* same as GXV_LookupValueDesc */
      FT_ULong   ul;
      FT_Char    c;
      FT_Short   s;       /* same as GXV_LookupValueDesc */
      FT_Long    l;
  
    } GXV_StateTable_GlyphOffsetDesc;
  
    typedef const GXV_StateTable_GlyphOffsetDesc* GXV_StateTable_GlyphOffsetCPtr;
  
    typedef void
    (*GXV_StateTable_Subtable_Setup_Func)( FT_UShort      table_size,
                                           FT_UShort      classTable,
                                           FT_UShort      stateArray,
                                           FT_UShort      entryTable,
                                           FT_UShort*     classTable_length_p,
                                           FT_UShort*     stateArray_length_p,
                                           FT_UShort*     entryTable_length_p,
                                           GXV_Validator  gxvalid );
  
    typedef void
    (*GXV_StateTable_Entry_Validate_Func)(
       FT_Byte                         state,
       FT_UShort                       flags,
       GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
       FT_Bytes                        statetable_table,
       FT_Bytes                        statetable_limit,
       GXV_Validator                   gxvalid );
  
    typedef void
    (*GXV_StateTable_OptData_Load_Func)( FT_Bytes       table,
                                         FT_Bytes       limit,
                                         GXV_Validator  gxvalid );
  
    typedef struct  GXV_StateTable_ValidatorRec_
    {
      GXV_GlyphOffset_Format              entry_glyphoffset_fmt;
      void*                               optdata;
  
      GXV_StateTable_Subtable_Setup_Func  subtable_setup_func;
      GXV_StateTable_Entry_Validate_Func  entry_validate_func;
      GXV_StateTable_OptData_Load_Func    optdata_load_func;
  
    } GXV_StateTable_ValidatorRec, *GXV_StateTable_ValidatorRecData;
  
  
    /* ---------------------- 32bit XStateTable ---------------------------- */
  
    typedef GXV_StateTable_GlyphOffsetDesc  GXV_XStateTable_GlyphOffsetDesc;
  
    typedef const GXV_XStateTable_GlyphOffsetDesc* GXV_XStateTable_GlyphOffsetCPtr;
  
    typedef void
    (*GXV_XStateTable_Subtable_Setup_Func)( FT_ULong       table_size,
                                            FT_ULong       classTable,
                                            FT_ULong       stateArray,
                                            FT_ULong       entryTable,
                                            FT_ULong*      classTable_length_p,
                                            FT_ULong*      stateArray_length_p,
                                            FT_ULong*      entryTable_length_p,
                                            GXV_Validator  gxvalid );
  
    typedef void
    (*GXV_XStateTable_Entry_Validate_Func)(
       FT_UShort                       state,
       FT_UShort                       flags,
       GXV_StateTable_GlyphOffsetCPtr  glyphOffset_p,
       FT_Bytes                        xstatetable_table,
       FT_Bytes                        xstatetable_limit,
       GXV_Validator                   gxvalid );
  
  
    typedef GXV_StateTable_OptData_Load_Func  GXV_XStateTable_OptData_Load_Func;
  
  
    typedef struct  GXV_XStateTable_ValidatorRec_
    {
      int                                  entry_glyphoffset_fmt;
      void*                                optdata;
  
      GXV_XStateTable_Subtable_Setup_Func  subtable_setup_func;
      GXV_XStateTable_Entry_Validate_Func  entry_validate_func;
      GXV_XStateTable_OptData_Load_Func    optdata_load_func;
  
      FT_ULong                             nClasses;
      FT_UShort                            maxClassID;
  
    } GXV_XStateTable_ValidatorRec, *GXV_XStateTable_ValidatorRecData;
  
  
    /* ===================================================================== */
  
    typedef struct  GXV_ValidatorRec_
    {
      FT_Validator  root;
  
      FT_Face       face;
      void*         table_data;
  
      FT_ULong      subtable_length;
  
      GXV_LookupValue_SignSpec        lookupval_sign;
      GXV_Lookup_Value_Validate_Func  lookupval_func;
      GXV_Lookup_Fmt4_Transit_Func    lookupfmt4_trans;
      FT_Bytes                        lookuptbl_head;
  
      FT_UShort  min_gid;
      FT_UShort  max_gid;
  
      GXV_StateTable_ValidatorRec     statetable;
      GXV_XStateTable_ValidatorRec    xstatetable;
  
  #ifdef FT_DEBUG_LEVEL_TRACE
      FT_UInt             debug_indent;
      const FT_String*    debug_function_name[3];
  #endif
  
    } GXV_ValidatorRec;
  
  
  #define GXV_TABLE_DATA( tag, field )                             \
          ( ( (GXV_ ## tag ## _Data)gxvalid->table_data )->field )
  
  #undef  FT_INVALID_
  #define FT_INVALID_( _error )                                     \
            ft_validator_error( gxvalid->root, FT_THROW( _error ) )
  
  #define GXV_LIMIT_CHECK( _count )                                       \
            FT_BEGIN_STMNT                                                \
              if ( p + _count > ( limit? limit : gxvalid->root->limit ) ) \
                FT_INVALID_TOO_SHORT;                                     \
            FT_END_STMNT
  
  
  #ifdef FT_DEBUG_LEVEL_TRACE
  
  #define GXV_INIT  gxvalid->debug_indent = 0
  
  #define GXV_NAME_ENTER( name )                                \
            FT_BEGIN_STMNT                                      \
              gxvalid->debug_indent += 2;                       \
              FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \
              FT_TRACE4(( "%s table\n", name ));                \
            FT_END_STMNT
  
  #define GXV_EXIT  gxvalid->debug_indent -= 2
  
  #define GXV_TRACE( s )                                        \
            FT_BEGIN_STMNT                                      \
              FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \
              FT_TRACE4( s );                                   \
            FT_END_STMNT
  
  #else /* !FT_DEBUG_LEVEL_TRACE */
  
  #define GXV_INIT                do { } while ( 0 )
  #define GXV_NAME_ENTER( name )  do { } while ( 0 )
  #define GXV_EXIT                do { } while ( 0 )
  
  #define GXV_TRACE( s )          do { } while ( 0 )
  
  #endif  /* !FT_DEBUG_LEVEL_TRACE */
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                    32bit alignment checking                   *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
  #define GXV_32BIT_ALIGNMENT_VALIDATE( a ) \
            FT_BEGIN_STMNT                  \
              {                             \
                if ( (a) & 3 )              \
                  FT_INVALID_OFFSET;        \
              }                             \
            FT_END_STMNT
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                    Dumping Binary Data                        *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
  #define GXV_TRACE_HEXDUMP( p, len )                     \
            FT_BEGIN_STMNT                                \
              {                                           \
                FT_Bytes  b;                              \
                                                          \
                                                          \
                for ( b = p; b < (FT_Bytes)p + len; b++ ) \
                  FT_TRACE1(("\\x%02x", *b));             \
              }                                           \
            FT_END_STMNT
  
  #define GXV_TRACE_HEXDUMP_C( p, len )                   \
            FT_BEGIN_STMNT                                \
              {                                           \
                FT_Bytes  b;                              \
                                                          \
                                                          \
                for ( b = p; b < (FT_Bytes)p + len; b++ ) \
                  if ( 0x40 < *b && *b < 0x7E )           \
                    FT_TRACE1(("%c", *b));                \
                  else                                    \
                    FT_TRACE1(("\\x%02x", *b));           \
              }                                           \
            FT_END_STMNT
  
  #define GXV_TRACE_HEXDUMP_SFNTNAME( n )               \
            GXV_TRACE_HEXDUMP( n.string, n.string_len )
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                         LOOKUP TABLE                          *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( void )
    gxv_BinSrchHeader_validate( FT_Bytes       p,
                                FT_Bytes       limit,
                                FT_UShort*     unitSize_p,
                                FT_UShort*     nUnits_p,
                                GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_LookupTable_validate( FT_Bytes       table,
                              FT_Bytes       limit,
                              GXV_Validator  gxvalid );
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                          Glyph ID                             *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( FT_Int )
    gxv_glyphid_validate( FT_UShort      gid,
                          GXV_Validator  gxvalid );
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                        CONTROL POINT                          *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( void )
    gxv_ctlPoint_validate( FT_UShort      gid,
                           FT_UShort      ctl_point,
                           GXV_Validator  gxvalid );
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                          SFNT NAME                            *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( void )
    gxv_sfntName_validate( FT_UShort      name_index,
                           FT_UShort      min_index,
                           FT_UShort      max_index,
                           GXV_Validator  gxvalid );
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                          STATE TABLE                          *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( void )
    gxv_StateTable_subtable_setup( FT_UShort      table_size,
                                   FT_UShort      classTable,
                                   FT_UShort      stateArray,
                                   FT_UShort      entryTable,
                                   FT_UShort*     classTable_length_p,
                                   FT_UShort*     stateArray_length_p,
                                   FT_UShort*     entryTable_length_p,
                                   GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_XStateTable_subtable_setup( FT_ULong       table_size,
                                    FT_ULong       classTable,
                                    FT_ULong       stateArray,
                                    FT_ULong       entryTable,
                                    FT_ULong*      classTable_length_p,
                                    FT_ULong*      stateArray_length_p,
                                    FT_ULong*      entryTable_length_p,
                                    GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_StateTable_validate( FT_Bytes       table,
                             FT_Bytes       limit,
                             GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_XStateTable_validate( FT_Bytes       table,
                              FT_Bytes       limit,
                              GXV_Validator  gxvalid );
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                 UTILITY MACROS AND FUNCTIONS                  *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    FT_LOCAL( void )
    gxv_array_getlimits_byte( FT_Bytes       table,
                              FT_Bytes       limit,
                              FT_Byte*       min,
                              FT_Byte*       max,
                              GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_array_getlimits_ushort( FT_Bytes       table,
                                FT_Bytes       limit,
                                FT_UShort*     min,
                                FT_UShort*     max,
                                GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_set_length_by_ushort_offset( FT_UShort*     offset,
                                     FT_UShort**    length,
                                     FT_UShort*     buff,
                                     FT_UInt        nmemb,
                                     FT_UShort      limit,
                                     GXV_Validator  gxvalid );
  
    FT_LOCAL( void )
    gxv_set_length_by_ulong_offset( FT_ULong*      offset,
                                    FT_ULong**     length,
                                    FT_ULong*      buff,
                                    FT_UInt        nmemb,
                                    FT_ULong       limit,
                                    GXV_Validator  gxvalid);
  
  
  #define GXV_SUBTABLE_OFFSET_CHECK( _offset )          \
            FT_BEGIN_STMNT                              \
              if ( (_offset) > gxvalid->subtable_length ) \
                FT_INVALID_OFFSET;                      \
            FT_END_STMNT
  
  #define GXV_SUBTABLE_LIMIT_CHECK( _count )                  \
            FT_BEGIN_STMNT                                    \
              if ( ( p + (_count) - gxvalid->subtable_start ) > \
                     gxvalid->subtable_length )                 \
                FT_INVALID_TOO_SHORT;                         \
            FT_END_STMNT
  
  #define GXV_USHORT_TO_SHORT( _us )                                    \
            ( ( 0x8000U < ( _us ) ) ? ( ( _us ) - 0x8000U ) : ( _us ) )
  
  #define GXV_STATETABLE_HEADER_SIZE  ( 2 + 2 + 2 + 2 )
  #define GXV_STATEHEADER_SIZE        GXV_STATETABLE_HEADER_SIZE
  
  #define GXV_XSTATETABLE_HEADER_SIZE  ( 4 + 4 + 4 + 4 )
  #define GXV_XSTATEHEADER_SIZE        GXV_XSTATETABLE_HEADER_SIZE
  
  
    /*************************************************************************/
    /*************************************************************************/
    /*****                                                               *****/
    /*****                        Table overlapping                      *****/
    /*****                                                               *****/
    /*************************************************************************/
    /*************************************************************************/
  
    typedef struct  GXV_odtect_DataRec_
    {
      FT_Bytes    start;
      FT_ULong    length;
      FT_String*  name;
  
    } GXV_odtect_DataRec,  *GXV_odtect_Data;
  
    typedef struct  GXV_odtect_RangeRec_
    {
      FT_UInt          nRanges;
      GXV_odtect_Data  range;
  
    } GXV_odtect_RangeRec, *GXV_odtect_Range;
  
  
    FT_LOCAL( void )
    gxv_odtect_add_range( FT_Bytes          start,
                          FT_ULong          length,
                          const FT_String*  name,
                          GXV_odtect_Range  odtect );
  
    FT_LOCAL( void )
    gxv_odtect_validate( GXV_odtect_Range  odtect,
                         GXV_Validator     gxvalid );
  
  
  #define GXV_ODTECT( n, odtect )                              \
            GXV_odtect_DataRec   odtect ## _range[n];          \
            GXV_odtect_RangeRec  odtect ## _rec = { 0, NULL }; \
            GXV_odtect_Range     odtect = NULL
  
  #define GXV_ODTECT_INIT( odtect )                      \
            FT_BEGIN_STMNT                               \
              odtect ## _rec.nRanges = 0;                \
              odtect ## _rec.range   = odtect ## _range; \
              odtect                 = & odtect ## _rec; \
            FT_END_STMNT
  
  
   /* */
  
  FT_END_HEADER
  
  #endif /* GXVCOMMN_H_ */
  
  
  /* END */
  