From 93e6b3e8e955d23d759ef0310c666b4aac915f79 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sat, 13 Nov 2021 14:41:40 +0100 Subject: [PATCH] [truetype] Updates for the forthcoming OpenType 1.9 standard (1/2). This is in preparation for implementing `DeltaSetIndexMap` format 1, which is used by `COLR` v1 tables, and which allows 32bit indices. https://docs.microsoft.com/en-us/typography/opentype/otspec190/delta/otvarcommonformats_delta.html * src/truetype/ttgxvar.h (GX_DeltaSetIdxMapRec): Change type of `mapCount` to `FT_ULong`. * src/truetype/ttgxvar.c (ft_var_load_delta_set_index_mapping): Add argument for passing the table size; update caller. Implement new format. --- src/truetype/ttgxvar.c | 62 +++++++++++++++++++++++++++++++----------- src/truetype/ttgxvar.h | 6 ++-- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 4fda29962..553e27d0c 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -664,37 +664,66 @@ ft_var_load_delta_set_index_mapping( TT_Face face, FT_ULong offset, GX_DeltaSetIdxMap map, - GX_ItemVarStore itemStore ) + GX_ItemVarStore itemStore, + FT_ULong table_len ) { FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; - FT_Error error; + FT_Error error; - FT_UShort format; - FT_UInt entrySize; - FT_UInt innerBitCount; - FT_UInt innerIndexMask; - FT_UInt i, j; + FT_Byte format; + FT_Byte entryFormat; + FT_UInt entrySize; + FT_UInt innerBitCount; + FT_UInt innerIndexMask; + FT_ULong i; + FT_UInt j; - if ( FT_STREAM_SEEK( offset ) || - FT_READ_USHORT( format ) || - FT_READ_USHORT( map->mapCount ) ) + if ( FT_STREAM_SEEK( offset ) || + FT_READ_BYTE( format ) || + FT_READ_BYTE( entryFormat ) ) goto Exit; - if ( format & 0xFFC0 ) + if ( format == 0 ) + { + if ( FT_READ_USHORT( map->mapCount ) ) + goto Exit; + } + else if ( format == 1 ) /* new in OpenType 1.9 */ + { + if ( FT_READ_ULONG( map->mapCount ) ) + goto Exit; + } + else { FT_TRACE2(( "bad map format %d\n", format )); error = FT_THROW( Invalid_Table ); goto Exit; } + if ( entryFormat & 0xC0 ) + { + FT_TRACE2(( "bad entry format %d\n", format )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + /* bytes per entry: 1, 2, 3, or 4 */ - entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; - innerBitCount = ( format & 0x000F ) + 1; + entrySize = ( ( entryFormat & 0x30 ) >> 4 ) + 1; + innerBitCount = ( entryFormat & 0x0F ) + 1; innerIndexMask = ( 1 << innerBitCount ) - 1; + /* rough sanity check */ + if ( map->mapCount * entrySize > table_len ) + { + FT_TRACE1(( "ft_var_load_delta_set_index_mapping:" + " invalid number of delta-set index mappings\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) ) goto Exit; @@ -723,7 +752,7 @@ if ( outerIndex >= itemStore->dataCount ) { - FT_TRACE2(( "outerIndex[%d] == %d out of range\n", + FT_TRACE2(( "outerIndex[%ld] == %d out of range\n", i, outerIndex )); error = FT_THROW( Invalid_Table ); @@ -736,7 +765,7 @@ if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) { - FT_TRACE2(( "innerIndex[%d] == %d out of range\n", + FT_TRACE2(( "innerIndex[%ld] == %d out of range\n", i, innerIndex )); error = FT_THROW( Invalid_Table ); @@ -861,7 +890,8 @@ face, table_offset + widthMap_offset, &table->widthMap, - &table->itemStore ); + &table->itemStore, + table_len ); if ( error ) goto Exit; } diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h index c58731951..ded9ea1d6 100644 --- a/src/truetype/ttgxvar.h +++ b/src/truetype/ttgxvar.h @@ -106,9 +106,9 @@ FT_BEGIN_HEADER typedef struct GX_DeltaSetIdxMapRec_ { - FT_UInt mapCount; - FT_UInt* outerIndex; /* indices to item var data */ - FT_UInt* innerIndex; /* indices to delta set */ + FT_ULong mapCount; + FT_UInt* outerIndex; /* indices to item var data */ + FT_UInt* innerIndex; /* indices to delta set */ } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;