ref: 7c75b166c8bd767a78ad55dbd16dadf1e026a1c7
parent: 3b125e95944ef4cbf321479410391db9bf403c00
author: Werner Lemberg <[email protected]>
date: Sat Dec 17 08:28:24 EST 2016
[sfnt, truetype] Various sanitizing fixes. * src/sfnt/sfobjs.c (sfnt_init_face): If the axis count in `fvar' is zero, set `num_instances' to zero. * src/truetype/ttgxvar.c (TT_Get_MM_Var): Handle `fvar' table with zero axes as invalid. * src/truetype/ttobjs.c (tt_face_init): Improve logic of loading `loca', `cvt', `fpgm', and `prep' table.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2016-12-17 Werner Lemberg <[email protected]>
+ [sfnt, truetype] Various sanitizing fixes.
+
+ * src/sfnt/sfobjs.c (sfnt_init_face): If the axis count in `fvar' is
+ zero, set `num_instances' to zero.
+
+ * src/truetype/ttgxvar.c (TT_Get_MM_Var): Handle `fvar' table with
+ zero axes as invalid.
+
+ * src/truetype/ttobjs.c (tt_face_init): Improve logic of loading
+ `loca', `cvt', `fpgm', and `prep' table.
+
+2016-12-17 Werner Lemberg <[email protected]>
+
Improve tracing of `FT_Open_Face'.
* src/base/ftobjs.c (FT_Open_Face): Return info on number of
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -967,6 +967,7 @@
/* based on similar code in function `TT_Get_MM_Var' */
if ( version != 0x00010000UL ||
axis_size != 20 ||
+ num_axes == 0 ||
num_axes > 0x3FFE ||
instance_size != 4 + 4 * num_axes ||
num_instances > 0x7EFF ||
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -1355,6 +1355,7 @@
fvar_head.countSizePairs != 2 ||
#endif
fvar_head.axisSize != 20 ||
+ fvar_head.axisCount == 0 ||
/* axisCount limit implied by 16-bit instanceSize */
fvar_head.axisCount > 0x3FFE ||
fvar_head.instanceCount > 0x7EFF ||
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -581,14 +581,30 @@
#ifdef FT_CONFIG_OPTION_INCREMENTAL
if ( !ttface->internal->incremental_interface )
+ {
error = tt_face_load_loca( face, stream );
- if ( !error )
- error = tt_face_load_cvt( face, stream );
- if ( !error )
- error = tt_face_load_fpgm( face, stream );
- if ( !error )
- error = tt_face_load_prep( face, stream );
+ /* having a (non-zero) `glyf' table without */
+ /* a `loca' table is not valid */
+ if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
+ goto Exit;
+ if ( error )
+ goto Exit;
+ }
+
+ /* `fpgm', `cvt', and `prep' are optional */
+ error = tt_face_load_cvt( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
+
+ error = tt_face_load_fpgm( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
+
+ error = tt_face_load_prep( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
+
/* Check the scalable flag based on `loca'. */
if ( !ttface->internal->incremental_interface &&
ttface->num_fixed_sizes &&
@@ -605,14 +621,27 @@
#else /* !FT_CONFIG_OPTION_INCREMENTAL */
- if ( !error )
- error = tt_face_load_loca( face, stream );
- if ( !error )
- error = tt_face_load_cvt( face, stream );
- if ( !error )
- error = tt_face_load_fpgm( face, stream );
- if ( !error )
- error = tt_face_load_prep( face, stream );
+ error = tt_face_load_loca( face, stream );
+
+ /* having a (non-zero) `glyf' table without */
+ /* a `loca' table is not valid */
+ if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
+ goto Exit;
+ if ( error )
+ goto Exit;
+
+ /* `fpgm', `cvt', and `prep' are optional */
+ error = tt_face_load_cvt( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
+
+ error = tt_face_load_fpgm( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
+
+ error = tt_face_load_prep( face, stream );
+ if ( error && FT_ERR_NEQ( error, Table_Missing ) )
+ goto Exit;
/* Check the scalable flag based on `loca'. */
if ( ttface->num_fixed_sizes &&
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -89,7 +89,6 @@
face->glyf_offset = FT_STREAM_POS();
}
-
FT_TRACE2(( "Locations " ));
error = face->goto_table( face, TTAG_loca, stream, &table_len );
if ( error )