[truetype] More sanity tests for GX handling.
These tests should mainly help avoid unnecessarily large memory allocations in case of malformed fonts. * src/truetype/ttgxvar.c (ft_var_readpackedpoints, ft_var_readpackeddeltas): Check number of points against stream size. (ft_var_load_avar): Check `pairCount' against table length. (ft_var_load_gvar): Check `globalCoordCount' and `glyphCount' against table length. (tt_face_vary_cvt): Check `tupleCount' and `offsetToData'. Fix trace. (TT_Vary_Apply_Glyph_Deltas): Fix trace. Free `sharedpoints' to avoid memory leak.
This commit is contained in:
parent
c220d8b498
commit
da34673e54
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
2015-10-10 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] More sanity tests for GX handling.
|
||||
|
||||
These tests should mainly help avoid unnecessarily large memory
|
||||
allocations in case of malformed fonts.
|
||||
|
||||
* src/truetype/ttgxvar.c (ft_var_readpackedpoints,
|
||||
ft_var_readpackeddeltas): Check number of points against stream
|
||||
size.
|
||||
(ft_var_load_avar): Check `pairCount' against table length.
|
||||
(ft_var_load_gvar): Check `globalCoordCount' and `glyphCount'
|
||||
against table length.
|
||||
(tt_face_vary_cvt): Check `tupleCount' and `offsetToData'.
|
||||
Fix trace.
|
||||
(TT_Vary_Apply_Glyph_Deltas): Fix trace.
|
||||
Free `sharedpoints' to avoid memory leak.
|
||||
|
||||
2015-10-10 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] Better protection against malformed GX data (#46166).
|
||||
|
@ -149,6 +149,12 @@
|
||||
n |= FT_GET_BYTE();
|
||||
}
|
||||
|
||||
if ( n > stream->size - stream->pos )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( FT_NEW_ARRAY( points, n ) )
|
||||
return NULL;
|
||||
|
||||
@ -233,6 +239,12 @@
|
||||
FT_UNUSED( error );
|
||||
|
||||
|
||||
if ( delta_cnt > stream->size - stream->pos )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
|
||||
return NULL;
|
||||
|
||||
@ -341,7 +353,8 @@
|
||||
FT_TRACE5(( " axis %d:\n", i ));
|
||||
|
||||
segment->pairCount = FT_GET_USHORT();
|
||||
if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
|
||||
if ( (FT_ULong)segment->pairCount * 4 > table_len ||
|
||||
FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
|
||||
{
|
||||
/* Failure. Free everything we have done so far. We must do */
|
||||
/* it right now since loading the `avar' table is optional. */
|
||||
@ -447,10 +460,6 @@
|
||||
if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
|
||||
goto Exit;
|
||||
|
||||
blend->tuplecount = gvar_head.globalCoordCount;
|
||||
blend->gv_glyphcnt = gvar_head.glyphCount;
|
||||
offsetToData = gvar_start + gvar_head.offsetToData;
|
||||
|
||||
if ( gvar_head.version != 0x00010000L )
|
||||
{
|
||||
FT_TRACE1(( "bad table version\n" ));
|
||||
@ -458,8 +467,6 @@
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
FT_TRACE2(( "loaded\n" ));
|
||||
|
||||
if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
|
||||
@ -468,6 +475,27 @@
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* rough sanity check, ignoring offsets */
|
||||
if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
|
||||
table_len / 2 )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_load_gvar:"
|
||||
" invalid number of global coordinates\n" ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* rough sanity check: offsets can be either 2 or 4 bytes, */
|
||||
/* and a single variation needs at least 4 bytes per glyph */
|
||||
if ( (FT_ULong)gvar_head.glyphCount *
|
||||
( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len )
|
||||
|
||||
FT_TRACE2(( "loaded\n" ));
|
||||
|
||||
blend->tuplecount = gvar_head.globalCoordCount;
|
||||
blend->gv_glyphcnt = gvar_head.glyphCount;
|
||||
offsetToData = gvar_start + gvar_head.offsetToData;
|
||||
|
||||
FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
|
||||
blend->tuplecount ));
|
||||
|
||||
@ -1353,13 +1381,25 @@
|
||||
goto FExit;
|
||||
|
||||
tupleCount = FT_GET_USHORT();
|
||||
offsetToData = table_start + FT_GET_USHORT();
|
||||
offsetToData = FT_GET_USHORT();
|
||||
|
||||
/* The documentation implies there are flags packed into the */
|
||||
/* tuplecount, but John Jenkins says that shared points don't apply */
|
||||
/* to `cvar', and no other flags are defined. */
|
||||
/* rough sanity test */
|
||||
if ( offsetToData + tupleCount * 4 > table_len )
|
||||
{
|
||||
FT_TRACE2(( "tt_face_vary_cvt:"
|
||||
" invalid CVT variation array header\n" ));
|
||||
|
||||
FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount ));
|
||||
error = FT_THROW( Invalid_Table );
|
||||
goto FExit;
|
||||
}
|
||||
|
||||
offsetToData += table_start;
|
||||
|
||||
/* The documentation implies there are flags packed into */
|
||||
/* `tupleCount', but John Jenkins says that shared points don't apply */
|
||||
/* to `cvar', and no other flags are defined. */
|
||||
|
||||
FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
|
||||
|
||||
for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
|
||||
{
|
||||
@ -1833,7 +1873,8 @@
|
||||
FT_Stream_SeekSet( stream, here );
|
||||
}
|
||||
|
||||
FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount ));
|
||||
FT_TRACE5(( "gvar: there are %d tuples:\n",
|
||||
tupleCount & GX_TC_TUPLE_COUNT_MASK ));
|
||||
|
||||
for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
|
||||
{
|
||||
@ -2013,6 +2054,8 @@
|
||||
|
||||
if ( localpoints != ALL_POINTS )
|
||||
FT_FREE( localpoints );
|
||||
if ( sharedpoints != ALL_POINTS )
|
||||
FT_FREE( sharedpoints );
|
||||
FT_FREE( deltas_x );
|
||||
FT_FREE( deltas_y );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user