[truetype] Fix handling of packed deltas in Variation Fonts.
* src/truetype/ttgxvar (ft_var_readpackeddeltas): Don't expect the number of bytes used to encode the deltas to be higher than the number of encoded values. The specification allows a very compact encoding; for example, a list of 200 zeros can be encoded with just a couple of bytes. We now count the consumed bytes to make sure to not read more than expected.
This commit is contained in:
parent
9ed5332fe6
commit
fc55291b1c
@ -264,55 +264,80 @@
|
||||
FT_Fixed *deltas = NULL;
|
||||
FT_UInt runcnt, cnt;
|
||||
FT_UInt i, j;
|
||||
FT_UInt bytes_used;
|
||||
FT_Memory memory = stream->memory;
|
||||
FT_Error error = FT_Err_Ok;
|
||||
|
||||
FT_UNUSED( error );
|
||||
|
||||
|
||||
if ( delta_cnt > size )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while ( i < delta_cnt )
|
||||
i = 0;
|
||||
bytes_used = 0;
|
||||
|
||||
while ( i < delta_cnt && bytes_used < size )
|
||||
{
|
||||
runcnt = FT_GET_BYTE();
|
||||
cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
|
||||
|
||||
bytes_used++;
|
||||
|
||||
if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
|
||||
{
|
||||
/* `runcnt' zeroes get added */
|
||||
/* `cnt` + 1 zeroes get added */
|
||||
for ( j = 0; j <= cnt && i < delta_cnt; j++ )
|
||||
deltas[i++] = 0;
|
||||
}
|
||||
else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
|
||||
{
|
||||
/* `runcnt' shorts from the stack */
|
||||
/* `cnt` + 1 shorts from the stack */
|
||||
bytes_used += 2 * ( cnt + 1 );
|
||||
if ( bytes_used > size )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas:"
|
||||
" number of short deltas too large\n" ));
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
for ( j = 0; j <= cnt && i < delta_cnt; j++ )
|
||||
deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* `runcnt' signed bytes from the stack */
|
||||
/* `cnt` + 1 signed bytes from the stack */
|
||||
bytes_used += cnt + 1;
|
||||
if ( bytes_used > size )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas:"
|
||||
" number of byte deltas too large\n" ));
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
for ( j = 0; j <= cnt && i < delta_cnt; j++ )
|
||||
deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
|
||||
}
|
||||
|
||||
if ( j <= cnt )
|
||||
{
|
||||
/* bad format */
|
||||
FT_FREE( deltas );
|
||||
return NULL;
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas:"
|
||||
" number of deltas too large\n" ));
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i < delta_cnt )
|
||||
{
|
||||
FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
return deltas;
|
||||
|
||||
Fail:
|
||||
FT_FREE( deltas );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user