Commit 7c75b166c8bd767a78ad55dbd16dadf1e026a1c7

Werner Lemberg 2016-12-17T13:28:24

[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.

diff --git a/ChangeLog b/ChangeLog
index 3376a24..9b9d822 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2016-12-17  Werner Lemberg  <wl@gnu.org>
 
+	[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  <wl@gnu.org>
+
 	Improve tracing of `FT_Open_Face'.
 
 	* src/base/ftobjs.c (FT_Open_Face): Return info on number of
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index b3b9761..efda0c1 100644
--- 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                     ||
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 12a3160..8746b25 100644
--- 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                               ||
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 758eaeb..81577a4 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -581,13 +581,29 @@
 #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 &&
@@ -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          &&
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index cd1d27c..0079ebd 100644
--- 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 )