[woff2] Fix SFNT table checks.
Also reduce number of SFNT table lookups. Reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18065 * include/freetype/internal/wofftypes.h (WOFF2_InfoRec): Add fields `glyf_table', `loca_table', and `head_table'. * src/sfnt/sfwoff2.c (reconstruct_glyf): Update signature. Use table pointers in `info' parameter. (get_x_mins): Check `maxp_table' Use table pointers in `info' parameter. (reconstruct_font): Use and set table pointers in `info' parameter. Fix check for `glyf' and `loca' tables. Update call to `reconstruct_glyf'. (woff2_open_font): Updated.
This commit is contained in:
parent
1167bff3e9
commit
5a1a79c0e8
24
ChangeLog
24
ChangeLog
@ -1,6 +1,28 @@
|
||||
2019-10-08 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[woff2] Fix SFNT table checks.
|
||||
|
||||
Also reduce number of SFNT table lookups.
|
||||
|
||||
Reported as
|
||||
|
||||
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18065
|
||||
|
||||
* include/freetype/internal/wofftypes.h (WOFF2_InfoRec): Add fields
|
||||
`glyf_table', `loca_table', and `head_table'.
|
||||
|
||||
* src/sfnt/sfwoff2.c (reconstruct_glyf): Update signature.
|
||||
Use table pointers in `info' parameter.
|
||||
(get_x_mins): Check `maxp_table'
|
||||
Use table pointers in `info' parameter.
|
||||
(reconstruct_font): Use and set table pointers in `info' parameter.
|
||||
Fix check for `glyf' and `loca' tables.
|
||||
Update call to `reconstruct_glyf'.
|
||||
(woff2_open_font): Updated.
|
||||
|
||||
2019-10-06 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/sfnt/sfwoff2 (reconstruct_glyf): Fix reallocation.
|
||||
* src/sfnt/sfwoff2.c (reconstruct_glyf): Fix reallocation.
|
||||
|
||||
Reported as
|
||||
|
||||
|
@ -176,38 +176,6 @@ FT_BEGIN_HEADER
|
||||
} WOFF2_HeaderRec, *WOFF2_Header;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
* WOFF2_InfoRec
|
||||
*
|
||||
* @description:
|
||||
* Metadata for WOFF2 font that may be required for reconstruction of
|
||||
* sfnt tables.
|
||||
*
|
||||
* @fields:
|
||||
* header_checksum ::
|
||||
* Checksum of SFNT offset table.
|
||||
*
|
||||
* num_glyphs ::
|
||||
* Number of glyphs in the font.
|
||||
*
|
||||
* num_hmetrics ::
|
||||
* `numberOfHMetrics` field in the 'hhea' table.
|
||||
*
|
||||
* x_mins ::
|
||||
* `xMin` values of glyph bounding box.
|
||||
*/
|
||||
typedef struct WOFF2_InfoRec_
|
||||
{
|
||||
FT_ULong header_checksum;
|
||||
FT_UShort num_glyphs;
|
||||
FT_UShort num_hmetrics;
|
||||
FT_Short* x_mins;
|
||||
|
||||
} WOFF2_InfoRec, *WOFF2_Info;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
@ -236,6 +204,51 @@ FT_BEGIN_HEADER
|
||||
} WOFF2_TableRec, *WOFF2_Table;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
* WOFF2_InfoRec
|
||||
*
|
||||
* @description:
|
||||
* Metadata for WOFF2 font that may be required for reconstruction of
|
||||
* sfnt tables.
|
||||
*
|
||||
* @fields:
|
||||
* header_checksum ::
|
||||
* Checksum of SFNT offset table.
|
||||
*
|
||||
* num_glyphs ::
|
||||
* Number of glyphs in the font.
|
||||
*
|
||||
* num_hmetrics ::
|
||||
* `numberOfHMetrics` field in the 'hhea' table.
|
||||
*
|
||||
* x_mins ::
|
||||
* `xMin` values of glyph bounding box.
|
||||
*
|
||||
* glyf_table ::
|
||||
* A pointer to the `glyf' table record.
|
||||
*
|
||||
* loca_table ::
|
||||
* A pointer to the `loca' table record.
|
||||
*
|
||||
* head_table ::
|
||||
* A pointer to the `head' table record.
|
||||
*/
|
||||
typedef struct WOFF2_InfoRec_
|
||||
{
|
||||
FT_ULong header_checksum;
|
||||
FT_UShort num_glyphs;
|
||||
FT_UShort num_hmetrics;
|
||||
FT_Short* x_mins;
|
||||
|
||||
WOFF2_Table glyf_table;
|
||||
WOFF2_Table loca_table;
|
||||
WOFF2_Table head_table;
|
||||
|
||||
} WOFF2_InfoRec, *WOFF2_Info;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @struct:
|
||||
|
@ -827,9 +827,7 @@
|
||||
|
||||
static FT_Error
|
||||
reconstruct_glyf( FT_Stream stream,
|
||||
WOFF2_Table glyf_table,
|
||||
FT_ULong* glyf_checksum,
|
||||
WOFF2_Table loca_table,
|
||||
FT_ULong* loca_checksum,
|
||||
FT_Byte** sfnt_bytes,
|
||||
FT_ULong* sfnt_size,
|
||||
@ -887,11 +885,11 @@
|
||||
/* index_format = 1 => Long version `loca'. */
|
||||
expected_loca_length = ( index_format ? 4 : 2 ) *
|
||||
( (FT_ULong)num_glyphs + 1 );
|
||||
if ( loca_table->dst_length != expected_loca_length )
|
||||
if ( info->loca_table->dst_length != expected_loca_length )
|
||||
goto Fail;
|
||||
|
||||
offset = ( 2 + num_substreams ) * 4;
|
||||
if ( offset > glyf_table->TransformLength )
|
||||
if ( offset > info->glyf_table->TransformLength )
|
||||
goto Fail;
|
||||
|
||||
for ( i = 0; i < num_substreams; ++i )
|
||||
@ -901,7 +899,7 @@
|
||||
|
||||
if ( FT_READ_ULONG( substream_size ) )
|
||||
goto Fail;
|
||||
if ( substream_size > glyf_table->TransformLength - offset )
|
||||
if ( substream_size > info->glyf_table->TransformLength - offset )
|
||||
goto Fail;
|
||||
|
||||
substreams[i].start = pos + offset;
|
||||
@ -1196,11 +1194,11 @@
|
||||
info->x_mins[i] = x_min;
|
||||
}
|
||||
|
||||
glyf_table->dst_length = dest_offset - glyf_table->dst_offset;
|
||||
loca_table->dst_offset = dest_offset;
|
||||
info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset;
|
||||
info->loca_table->dst_offset = dest_offset;
|
||||
|
||||
/* `loca[n]' will be equal to the length of the `glyf' table. */
|
||||
loca_values[num_glyphs] = glyf_table->dst_length;
|
||||
loca_values[num_glyphs] = info->glyf_table->dst_length;
|
||||
|
||||
if ( store_loca( loca_values,
|
||||
num_glyphs + 1,
|
||||
@ -1212,11 +1210,11 @@
|
||||
memory ) )
|
||||
goto Fail;
|
||||
|
||||
loca_table->dst_length = dest_offset - loca_table->dst_offset;
|
||||
info->loca_table->dst_length = dest_offset - info->loca_table->dst_offset;
|
||||
|
||||
FT_TRACE4(( " loca table info:\n" ));
|
||||
FT_TRACE4(( " dst_offset = %lu\n", loca_table->dst_offset ));
|
||||
FT_TRACE4(( " dst_length = %lu\n", loca_table->dst_length ));
|
||||
FT_TRACE4(( " dst_offset = %lu\n", info->loca_table->dst_offset ));
|
||||
FT_TRACE4(( " dst_length = %lu\n", info->loca_table->dst_length ));
|
||||
FT_TRACE4(( " checksum = %09x\n", *loca_checksum ));
|
||||
|
||||
/* Set pointer `sfnt_bytes' to its correct value. */
|
||||
@ -1265,16 +1263,16 @@
|
||||
FT_Error error = FT_Err_Ok;
|
||||
FT_ULong offset_size;
|
||||
|
||||
const WOFF2_Table glyf_table = find_table( tables, num_tables,
|
||||
TTAG_glyf );
|
||||
const WOFF2_Table loca_table = find_table( tables, num_tables,
|
||||
TTAG_loca );
|
||||
const WOFF2_Table maxp_table = find_table( tables, num_tables,
|
||||
TTAG_maxp );
|
||||
const WOFF2_Table head_table = find_table( tables, num_tables,
|
||||
TTAG_head );
|
||||
const WOFF2_Table maxp_table = find_table( tables, num_tables,
|
||||
TTAG_maxp );
|
||||
|
||||
|
||||
if ( !maxp_table )
|
||||
{
|
||||
FT_ERROR(( "`maxp' table is missing.\n" ));
|
||||
return FT_THROW( Invalid_Table );
|
||||
}
|
||||
|
||||
/* Read `numGlyphs' field from `maxp' table. */
|
||||
if ( FT_STREAM_SEEK( maxp_table->src_offset ) && FT_STREAM_SKIP( 8 ) )
|
||||
return error;
|
||||
@ -1285,7 +1283,8 @@
|
||||
info->num_glyphs = num_glyphs;
|
||||
|
||||
/* Read `indexToLocFormat' field from `head' table. */
|
||||
if ( FT_STREAM_SEEK( head_table->src_offset ) && FT_STREAM_SKIP( 50 ) )
|
||||
if ( FT_STREAM_SEEK( info->head_table->src_offset ) &&
|
||||
FT_STREAM_SKIP( 50 ) )
|
||||
return error;
|
||||
|
||||
if ( FT_READ_USHORT( index_format ) )
|
||||
@ -1297,7 +1296,7 @@
|
||||
if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
|
||||
return error;
|
||||
|
||||
loca_offset = loca_table->src_offset;
|
||||
loca_offset = info->loca_table->src_offset;
|
||||
|
||||
for ( i = 0; i < num_glyphs; ++i )
|
||||
{
|
||||
@ -1320,7 +1319,7 @@
|
||||
glyf_offset = glyf_offset << 1;
|
||||
}
|
||||
|
||||
glyf_offset += glyf_table->src_offset;
|
||||
glyf_offset += info->glyf_table->src_offset;
|
||||
|
||||
if ( FT_STREAM_SEEK( glyf_offset ) && FT_STREAM_SKIP( 2 ) )
|
||||
return error;
|
||||
@ -1501,29 +1500,25 @@
|
||||
FT_ULong font_checksum = info->header_checksum;
|
||||
FT_Bool is_glyf_xform = FALSE;
|
||||
|
||||
FT_ULong table_entry_offset = 12;
|
||||
WOFF2_Table head_table;
|
||||
FT_ULong table_entry_offset = 12;
|
||||
|
||||
|
||||
/* A few table checks before reconstruction. */
|
||||
/* `glyf' must be present with `loca'. */
|
||||
const WOFF2_Table glyf_table = find_table( indices, num_tables,
|
||||
TTAG_glyf );
|
||||
const WOFF2_Table loca_table = find_table( indices, num_tables,
|
||||
TTAG_loca );
|
||||
info->glyf_table = find_table( indices, num_tables, TTAG_glyf );
|
||||
info->loca_table = find_table( indices, num_tables, TTAG_loca );
|
||||
|
||||
|
||||
if ( ( !glyf_table && loca_table ) ||
|
||||
( !loca_table && glyf_table ) )
|
||||
if ( !( info->glyf_table && info->loca_table ) )
|
||||
{
|
||||
FT_ERROR(( "Both `glyph' and `loca' tables must be present.\n" ));
|
||||
return FT_THROW( Invalid_Table );
|
||||
}
|
||||
|
||||
/* Both `glyf' and `loca' must have same transformation. */
|
||||
if ( glyf_table != NULL )
|
||||
if ( info->glyf_table != NULL )
|
||||
{
|
||||
if ( ( glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
|
||||
( loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
|
||||
if ( ( info->glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
|
||||
( info->loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
|
||||
{
|
||||
FT_ERROR(( "Transformation mismatch"
|
||||
" between `glyf' and `loca' table." ));
|
||||
@ -1605,9 +1600,7 @@
|
||||
table.dst_offset = dest_offset;
|
||||
|
||||
if ( reconstruct_glyf( stream,
|
||||
&table,
|
||||
&checksum,
|
||||
loca_table,
|
||||
&loca_checksum,
|
||||
&sfnt,
|
||||
sfnt_size,
|
||||
@ -1677,17 +1670,17 @@
|
||||
}
|
||||
|
||||
/* Update `head' checkSumAdjustment. */
|
||||
head_table = find_table( indices, num_tables, TTAG_head );
|
||||
if ( !head_table )
|
||||
info->head_table = find_table( indices, num_tables, TTAG_head );
|
||||
if ( !info->head_table )
|
||||
{
|
||||
FT_ERROR(( "`head' table is missing.\n" ));
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
if ( head_table->dst_length < 12 )
|
||||
if ( info->head_table->dst_length < 12 )
|
||||
goto Fail;
|
||||
|
||||
buf_cursor = sfnt + head_table->dst_offset + 8;
|
||||
buf_cursor = sfnt + info->head_table->dst_offset + 8;
|
||||
font_checksum = 0xB1B0AFBA - font_checksum;
|
||||
|
||||
WRITE_ULONG( buf_cursor, font_checksum );
|
||||
@ -1734,7 +1727,7 @@
|
||||
FT_Int face_index;
|
||||
|
||||
WOFF2_HeaderRec woff2;
|
||||
WOFF2_InfoRec info = { 0, 0, 0, NULL };
|
||||
WOFF2_InfoRec info = { 0, 0, 0, NULL, NULL, NULL, NULL };
|
||||
WOFF2_Table tables = NULL;
|
||||
WOFF2_Table* indices = NULL;
|
||||
WOFF2_Table* temp_indices = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user