Exemple #1
0
  /* parse single actSubrecord */
  static void
  gxv_just_actSubrecord_validate( FT_Bytes       table,
                                  FT_Bytes       limit,
                                  GXV_Validator  gxvalid )
  {
    FT_Bytes   p = table;
    FT_UShort  actionClass;
    FT_UShort  actionType;
    FT_ULong   actionLength;


    GXV_NAME_ENTER( "just actSubrecord" );

    GXV_LIMIT_CHECK( 2 + 2 + 4 );
    actionClass  = FT_NEXT_USHORT( p );
    actionType   = FT_NEXT_USHORT( p );
    actionLength = FT_NEXT_ULONG( p );

    /* actionClass is related with justClass using 7bit only */
    if ( ( actionClass & 0xFF80 ) != 0 )
      GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );

    if ( actionType == 0 )
      gxv_just_actSubrecord_type0_validate( p, limit, gxvalid );
    else if ( actionType == 1 )
      gxv_just_actSubrecord_type1_validate( p, limit, gxvalid );
    else if ( actionType == 2 )
      gxv_just_actSubrecord_type2_validate( p, limit, gxvalid );
    else if ( actionType == 3 )
      ;                         /* Stretch glyph action: no actionData */
    else if ( actionType == 4 )
      gxv_just_actSubrecord_type4_validate( p, limit, gxvalid );
    else if ( actionType == 5 )
      gxv_just_actSubrecord_type5_validate( p, limit, gxvalid );
    else
      FT_INVALID_DATA;

    gxvalid->subtable_length = actionLength;

    GXV_EXIT;
  }
Exemple #2
0
  gxv_feat_validate( FT_Bytes      table,
                     FT_Face       face,
                     FT_Validator  ftvalid )
  {
    GXV_ValidatorRec  gxvalidrec;
    GXV_Validator     gxvalid = &gxvalidrec;

    GXV_feat_DataRec  featrec;
    GXV_feat_Data     feat = &featrec;

    FT_Bytes          p     = table;
    FT_Bytes          limit = 0;

    FT_UInt           featureNameCount;

    FT_UInt           i;
    FT_Int            last_feature;


    gxvalid->root       = ftvalid;
    gxvalid->table_data = feat;
    gxvalid->face       = face;

    FT_TRACE3(( "validating `feat' table\n" ));
    GXV_INIT;

    feat->reserved_size = 0;

    /* version + featureNameCount + none_0 + none_1  */
    GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
    feat->reserved_size += 4 + 2 + 2 + 4;

    if ( FT_NEXT_ULONG( p ) != 0x00010000UL ) /* Version */
      FT_INVALID_FORMAT;

    featureNameCount = FT_NEXT_USHORT( p );
    GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount ));

    if ( !( IS_PARANOID_VALIDATION ) )
      p += 6; /* skip (none) and (none) */
    else
    {
      if ( FT_NEXT_USHORT( p ) != 0 )
        FT_INVALID_DATA;

      if ( FT_NEXT_ULONG( p )  != 0 )
        FT_INVALID_DATA;
    }

    feat->reserved_size += featureNameCount * ( 2 + 2 + 4 + 2 + 2 );

    for ( last_feature = -1, i = 0; i < featureNameCount; i++ )
    {
      gxv_feat_name_validate( p, limit, gxvalid );

      if ( (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
        GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );

      last_feature = GXV_FEAT_DATA( feature );
      p += 2 + 2 + 4 + 2 + 2;
    }

    FT_TRACE4(( "\n" ));
  }
Exemple #3
0
  static void
  gxv_feat_name_validate( FT_Bytes       table,
                          FT_Bytes       limit,
                          GXV_Validator  gxvalid )
  {
    FT_Bytes   p             = table;
    FT_UInt    reserved_size = GXV_FEAT_DATA( reserved_size );

    FT_UShort  feature;
    FT_UShort  nSettings;
    FT_ULong   settingTable;
    FT_UShort  featureFlags;

    FT_Bool    exclusive;
    FT_Int     last_setting;
    FT_UInt    i;


    GXV_NAME_ENTER( "name" );

    /* feature + nSettings + settingTable + featureFlags */
    GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );

    feature = FT_NEXT_USHORT( p );
    GXV_FEAT_DATA( feature ) = feature;

    nSettings    = FT_NEXT_USHORT( p );
    settingTable = FT_NEXT_ULONG ( p );
    featureFlags = FT_NEXT_USHORT( p );

    if ( settingTable < reserved_size )
      FT_INVALID_OFFSET;

    if ( ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
      GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );

    exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS );
    if ( exclusive )
    {
      FT_Byte  dynamic_default;


      if ( featureFlags & GXV_FEAT_MASK_DYNAMIC_DEFAULT )
        dynamic_default = (FT_Byte)( featureFlags &
                                     GXV_FEAT_MASK_DEFAULT_SETTING );
      else
        dynamic_default = 0;

      /* If exclusive, check whether default setting is in the range. */
      if ( !( dynamic_default < nSettings ) )
        FT_INVALID_FORMAT;
    }

    gxv_feat_registry_validate( feature, nSettings, exclusive, gxvalid );

    gxv_feat_name_index_validate( p, limit, gxvalid );

    p = gxvalid->root->base + settingTable;
    for ( last_setting = -1, i = 0; i < nSettings; i++ )
    {
      gxv_feat_setting_validate( p, limit, exclusive, gxvalid );

      if ( (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
        GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );

      last_setting = (FT_Int)GXV_FEAT_DATA( setting );
      /* setting + nameIndex */
      p += ( 2 + 2 );
    }

    GXV_EXIT;
  }
Exemple #4
0
  static void
  gxv_kern_subtable_fmt3_validate( FT_Bytes       table,
                                   FT_Bytes       limit,
                                   GXV_Validator  gxvalid )
  {
    FT_Bytes   p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
    FT_UShort  glyphCount;
    FT_Byte    kernValueCount;
    FT_Byte    leftClassCount;
    FT_Byte    rightClassCount;
    FT_Byte    flags;


    GXV_NAME_ENTER( "kern subtable format 3" );

    GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
    glyphCount      = FT_NEXT_USHORT( p );
    kernValueCount  = FT_NEXT_BYTE( p );
    leftClassCount  = FT_NEXT_BYTE( p );
    rightClassCount = FT_NEXT_BYTE( p );
    flags           = FT_NEXT_BYTE( p );

    if ( gxvalid->face->num_glyphs != glyphCount )
    {
      GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
                  gxvalid->face->num_glyphs, glyphCount ));
      GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
    }

    if ( flags != 0 )
      GXV_TRACE(( "kern subtable fmt3 has nonzero value"
                  " (%d) in unused flag\n", flags ));
    /*
     * just skip kernValue[kernValueCount]
     */
    GXV_LIMIT_CHECK( 2 * kernValueCount );
    p += 2 * kernValueCount;

    /*
     * check leftClass[gid] < leftClassCount
     */
    {
      FT_Byte  min, max;


      GXV_LIMIT_CHECK( glyphCount );
      gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, gxvalid );
      p += gxvalid->subtable_length;

      if ( leftClassCount < max )
        FT_INVALID_DATA;
    }

    /*
     * check rightClass[gid] < rightClassCount
     */
    {
      FT_Byte  min, max;


      GXV_LIMIT_CHECK( glyphCount );
      gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, gxvalid );
      p += gxvalid->subtable_length;

      if ( rightClassCount < max )
        FT_INVALID_DATA;
    }

    /*
     * check kernIndex[i, j] < kernValueCount
     */
    {
      FT_UShort  i, j;


      for ( i = 0; i < leftClassCount; i++ )
      {
        for ( j = 0; j < rightClassCount; j++ )
        {
          GXV_LIMIT_CHECK( 1 );
          if ( kernValueCount < FT_NEXT_BYTE( p ) )
            FT_INVALID_OFFSET;
        }
      }
    }

    gxvalid->subtable_length = (FT_ULong)( p - table );

    GXV_EXIT;
  }
Exemple #5
0
  static void
  gxv_mort_subtable_type2_ligActionOffset_validate(
    FT_Bytes       table,
    FT_UShort      ligActionOffset,
    GXV_Validator  gxvalid)
  {
    /* access ligActionTable */
    GXV_mort_subtable_type2_StateOptRecData  optdata =
      (GXV_mort_subtable_type2_StateOptRecData)gxvalid->statetable.optdata;

    FT_Bytes lat_base  = table + optdata->ligActionTable;
    FT_Bytes p         = table + ligActionOffset;
    FT_Bytes lat_limit = lat_base + optdata->ligActionTable;


    GXV_32BIT_ALIGNMENT_VALIDATE(ligActionOffset);
    if (p < lat_base)
    {
      GXV_TRACE(("too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
                  ligActionOffset, lat_base - p));

      /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
      GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET);
    }
    else if (lat_limit < p)
    {
      GXV_TRACE(("too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
                  ligActionOffset, p - lat_limit));

      /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
      GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET);
    }
    else
    {
      /* validate entry in ligActionTable */
      FT_ULong   lig_action;
#ifdef GXV_LOAD_UNUSED_VARS
      FT_UShort  last;
      FT_UShort  store;
#endif
      FT_ULong   offset;


      lig_action = FT_NEXT_ULONG(p);
#ifdef GXV_LOAD_UNUSED_VARS
      last   = (FT_UShort)((lig_action >> 31) & 1);
      store  = (FT_UShort)((lig_action >> 30) & 1);
#endif

      /* Apple spec defines this offset as a word offset */
      offset = lig_action & 0x3FFFFFFFUL;
      if (offset * 2 < optdata->ligatureTable)
      {
        GXV_TRACE(("too short offset 0x%08x:"
                    " 2 x offset < ligatureTable (%d byte rewind)\n",
                     offset, optdata->ligatureTable - offset * 2));

        GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET);
      } else if (offset * 2 >
                  optdata->ligatureTable + optdata->ligatureTable_length)
      {
        GXV_TRACE(("too long offset 0x%08x:"
                    " 2 x offset > ligatureTable + ligatureTable_length"
                    " (%d byte overrun)\n",
                     offset,
                     optdata->ligatureTable + optdata->ligatureTable_length
                     - offset * 2));

        GXV_SET_ERR_IF_PARANOID(FT_INVALID_OFFSET);
      }
    }
  }
Exemple #6
0
  static void
  gxv_morx_subtable_type2_ligActionIndex_validate(
    FT_Bytes       table,
    FT_UShort      ligActionIndex,
    GXV_Validator  gxvalid )
  {
    /* access ligActionTable */
    GXV_morx_subtable_type2_StateOptRecData optdata =
      (GXV_morx_subtable_type2_StateOptRecData)gxvalid->xstatetable.optdata;

    FT_Bytes lat_base  = table + optdata->ligActionTable;
    FT_Bytes p         = lat_base +
                         ligActionIndex * GXV_MORX_LIGACTION_ENTRY_SIZE;
    FT_Bytes lat_limit = lat_base + optdata->ligActionTable;


    if ( p < lat_base )
    {
      GXV_TRACE(( "p < lat_base (%d byte rewind)\n", lat_base - p ));
      FT_INVALID_OFFSET;
    }
    else if ( lat_limit < p )
    {
      GXV_TRACE(( "lat_limit < p (%d byte overrun)\n", p - lat_limit ));
      FT_INVALID_OFFSET;
    }

    {
      /* validate entry in ligActionTable */
      FT_ULong   lig_action;
#ifdef GXV_LOAD_UNUSED_VARS
      FT_UShort  last;
      FT_UShort  store;
#endif
      FT_ULong   offset;
      FT_Long    gid_limit;


      lig_action = FT_NEXT_ULONG( p );
#ifdef GXV_LOAD_UNUSED_VARS
      last       = (FT_UShort)( ( lig_action >> 31 ) & 1 );
      store      = (FT_UShort)( ( lig_action >> 30 ) & 1 );
#endif

      offset = lig_action & 0x3FFFFFFFUL;

      /* this offset is 30-bit signed value to add to GID */
      /* it is different from the location offset in mort */
      if ( ( offset & 0x3FFF0000UL ) == 0x3FFF0000UL )
      { /* negative offset */
        gid_limit = gxvalid->face->num_glyphs -
                    (FT_Long)( offset & 0x0000FFFFUL );
        if ( gid_limit > 0 )
          return;

        GXV_TRACE(( "ligature action table includes"
                    " too negative offset moving all GID"
                    " below defined range: 0x%04x\n",
                    offset & 0xFFFFU ));
        GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
      }
      else if ( ( offset & 0x3FFF0000UL ) == 0x00000000UL )
      { /* positive offset */
        if ( (FT_Long)offset < gxvalid->face->num_glyphs )
          return;

        GXV_TRACE(( "ligature action table includes"
                    " too large offset moving all GID"
                    " over defined range: 0x%04x\n",
                    offset & 0xFFFFU ));
        GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
      }

      GXV_TRACE(( "ligature action table includes"
                  " invalid offset to add to 16-bit GID:"
                  " 0x%08x\n", offset ));
      GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
    }
  }