summaryrefslogtreecommitdiff
path: root/src/truetype/ttgxvar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/truetype/ttgxvar.c')
-rw-r--r--src/truetype/ttgxvar.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index e4da8105b..48b79efa1 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -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;
}