Commit addb2dddb6fd4be32ea16b44831e4cc99bbc9693

Werner Lemberg 2017-06-03T21:05:42

[base, cff, truetype] Integer overflows. Reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2060 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2062 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2063 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2068 * src/base/ftobjs.c (ft_glyphslot_grid_fit_metrics): Use OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG. * src/cff/cf2blues.c (cf2_blues_capture), src/cff/cf2hints.c (cf2_hintmap_adjustHints): Use OVERFLOW_SUB_INT32. * src/truetype/ttgload.c (compute_glyph_metrics): User OVERFLOW_SUB_LONG. * src/truetype/ttinterp.c (Direct_Move, Direct_Move_Orig, Direct_Move_X, Direct_Move_Y, Direct_Move_Orig_X, Direct_Move_Orig_Y, Move_Zp2_Point, Ins_MSIRP): Use OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG.

diff --git a/ChangeLog b/ChangeLog
index f36748c..e3a42c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
 2017-06-03  Werner Lemberg  <wl@gnu.org>
 
+	[base, cff, truetype] Integer overflows.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2060
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2062
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2063
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2068
+
+	* src/base/ftobjs.c (ft_glyphslot_grid_fit_metrics): Use
+	OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG.
+
+	* src/cff/cf2blues.c (cf2_blues_capture), src/cff/cf2hints.c
+	(cf2_hintmap_adjustHints): Use OVERFLOW_SUB_INT32.
+
+	* src/truetype/ttgload.c (compute_glyph_metrics): User
+	OVERFLOW_SUB_LONG.
+
+	* src/truetype/ttinterp.c (Direct_Move, Direct_Move_Orig,
+	Direct_Move_X, Direct_Move_Y, Direct_Move_Orig_X,
+	Direct_Move_Orig_Y, Move_Zp2_Point, Ins_MSIRP): Use
+	OVERFLOW_ADD_LONG and OVERFLOW_SUB_LONG.
+
+2017-06-03  Werner Lemberg  <wl@gnu.org>
+
 	* builds/unix/freetype-config.in: Fix pkg-config test (#51162).
 
 	Patch directly taken from bug report.
@@ -2855,7 +2880,7 @@
 	[cff] Implement CFF2 support (2/2).
 
 	The font variation code.  All parts dependent on the GX code in the
-	`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. 
+	`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
 	In other words, you can still compile the `cff' module without
 	defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
 	support without font variation).
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 75e4988..cd5874c 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -581,28 +581,36 @@
       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 
-      right  = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );
-      bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );
+      right  = FT_PIX_CEIL( OVERFLOW_ADD_LONG( metrics->vertBearingX,
+                                               metrics->width ) );
+      bottom = FT_PIX_CEIL( OVERFLOW_ADD_LONG( metrics->vertBearingY,
+                                               metrics->height ) );
 
       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 
-      metrics->width  = right - metrics->vertBearingX;
-      metrics->height = bottom - metrics->vertBearingY;
+      metrics->width  = OVERFLOW_SUB_LONG( right,
+                                           metrics->vertBearingX );
+      metrics->height = OVERFLOW_SUB_LONG( bottom,
+                                           metrics->vertBearingY );
     }
     else
     {
       metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );
       metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );
 
-      right  = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );
-      bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );
+      right  = FT_PIX_CEIL ( OVERFLOW_ADD_LONG( metrics->horiBearingX,
+                                                metrics->width ) );
+      bottom = FT_PIX_FLOOR( OVERFLOW_SUB_LONG( metrics->horiBearingY,
+                                                metrics->height ) );
 
       metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );
       metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );
 
-      metrics->width  = right - metrics->horiBearingX;
-      metrics->height = metrics->horiBearingY - bottom;
+      metrics->width  = OVERFLOW_SUB_LONG( right,
+                                           metrics->horiBearingX );
+      metrics->height = OVERFLOW_SUB_LONG( metrics->horiBearingY,
+                                           bottom );
     }
 
     metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );
diff --git a/src/cff/cf2blues.c b/src/cff/cf2blues.c
index 950c714..a94254d 100644
--- a/src/cff/cf2blues.c
+++ b/src/cff/cf2blues.c
@@ -502,7 +502,8 @@
           if ( blues->suppressOvershoot )
             dsNew = blues->zone[i].dsFlatEdge;
 
-          else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >=
+          else if ( OVERFLOW_SUB_INT32( blues->zone[i].csTopEdge,
+                                        bottomHintEdge->csCoord ) >=
                       blues->blueShift )
           {
             /* guarantee minimum of 1 pixel overshoot */
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
index 89af2ff..d7938c9 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -512,8 +512,10 @@
         if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
           hintmap->edge[i - 1].scale =
             FT_DivFix(
-              hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord,
-              hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord );
+              OVERFLOW_SUB_INT32( hintmap->edge[i].dsCoord,
+                                  hintmap->edge[i - 1].dsCoord ),
+              OVERFLOW_SUB_INT32( hintmap->edge[i].csCoord,
+                                  hintmap->edge[i - 1].csCoord ) );
       }
 
       if ( isPair )
@@ -521,8 +523,10 @@
         if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
           hintmap->edge[j - 1].scale =
             FT_DivFix(
-              hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord,
-              hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord );
+              OVERFLOW_SUB_INT32( hintmap->edge[j].dsCoord,
+                                  hintmap->edge[j - 1].dsCoord ),
+              OVERFLOW_SUB_INT32( hintmap->edge[j].csCoord,
+                                  hintmap->edge[j - 1].csCoord ) );
 
         i += 1;     /* skip upper edge on next loop */
       }
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index e5a3da3..66e8228 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -2100,8 +2100,8 @@
     }
 
     /* set glyph dimensions */
-    glyph->metrics.width  = bbox.xMax - bbox.xMin;
-    glyph->metrics.height = bbox.yMax - bbox.yMin;
+    glyph->metrics.width  = OVERFLOW_SUB_LONG( bbox.xMax, bbox.xMin );
+    glyph->metrics.height = OVERFLOW_SUB_LONG( bbox.yMax, bbox.yMin );
 
     /* Now take care of vertical metrics.  In the case where there is */
     /* no vertical information within the font (relatively common),   */
@@ -2137,7 +2137,8 @@
         /*       table in the font.  Otherwise, we use the     */
         /*       values defined in the horizontal header.      */
 
-        height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
+        height = (FT_Short)FT_DivFix( OVERFLOW_SUB_LONG( bbox.yMax,
+                                                         bbox.yMin ),
                                       y_scale );
         if ( face->os2.version != 0xFFFFU )
           advance = (FT_Pos)( face->os2.sTypoAscender -
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index cbb7540..85e9e08 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -1676,7 +1676,9 @@
       if ( SUBPIXEL_HINTING_INFINALITY                            &&
            ( !exc->ignore_x_mode                                ||
              ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
-        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+        zone->cur[point].x = OVERFLOW_ADD_LONG(
+                               zone->cur[point].x,
+                               FT_MulDiv( distance, v, exc->F_dot_P ) );
       else
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
@@ -1685,12 +1687,16 @@
       /* diagonal moves, but only post-IUP.  DejaVu tries to adjust */
       /* diagonal stems like on `Z' and `z' post-IUP.               */
       if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
-        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+        zone->cur[point].x = OVERFLOW_ADD_LONG(
+                               zone->cur[point].x,
+                               FT_MulDiv( distance, v, exc->F_dot_P ) );
       else
 #endif
 
       if ( NO_SUBPIXEL_HINTING )
-        zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+        zone->cur[point].x = OVERFLOW_ADD_LONG(
+                               zone->cur[point].x,
+                               FT_MulDiv( distance, v, exc->F_dot_P ) );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
@@ -1705,7 +1711,9 @@
               exc->iupx_called            &&
               exc->iupy_called            ) )
 #endif
-        zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+        zone->cur[point].y = OVERFLOW_ADD_LONG(
+                               zone->cur[point].y,
+                               FT_MulDiv( distance, v, exc->F_dot_P ) );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -1741,12 +1749,16 @@
     v = exc->GS.freeVector.x;
 
     if ( v != 0 )
-      zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
+      zone->org[point].x = OVERFLOW_ADD_LONG(
+                             zone->org[point].x,
+                             FT_MulDiv( distance, v, exc->F_dot_P ) );
 
     v = exc->GS.freeVector.y;
 
     if ( v != 0 )
-      zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
+      zone->org[point].y = OVERFLOW_ADD_LONG(
+                             zone->org[point].y,
+                             FT_MulDiv( distance, v, exc->F_dot_P ) );
   }
 
 
@@ -1769,18 +1781,18 @@
   {
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode )
-      zone->cur[point].x += distance;
+      zone->cur[point].x = OVERFLOW_ADD_LONG( zone->cur[point].x, distance );
     else
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
     if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility )
-      zone->cur[point].x += distance;
+      zone->cur[point].x = OVERFLOW_ADD_LONG( zone->cur[point].x, distance );
     else
 #endif
 
     if ( NO_SUBPIXEL_HINTING )
-      zone->cur[point].x += distance;
+      zone->cur[point].x = OVERFLOW_ADD_LONG( zone->cur[point].x, distance );
 
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
   }
@@ -1799,7 +1811,7 @@
             exc->backward_compatibility          &&
             exc->iupx_called && exc->iupy_called ) )
 #endif
-      zone->cur[point].y += distance;
+      zone->cur[point].y = OVERFLOW_ADD_LONG( zone->cur[point].y, distance );
 
     zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
   }
@@ -1823,7 +1835,7 @@
   {
     FT_UNUSED( exc );
 
-    zone->org[point].x += distance;
+    zone->org[point].x = OVERFLOW_ADD_LONG( zone->org[point].x, distance );
   }
 
 
@@ -1835,7 +1847,7 @@
   {
     FT_UNUSED( exc );
 
-    zone->org[point].y += distance;
+    zone->org[point].y = OVERFLOW_ADD_LONG( zone->org[point].y, distance );
   }
 
 
@@ -5392,7 +5404,8 @@
       if ( !( SUBPIXEL_HINTING_MINIMAL    &&
               exc->backward_compatibility ) )
 #endif
-        exc->zp2.cur[point].x += dx;
+        exc->zp2.cur[point].x = OVERFLOW_ADD_LONG( exc->zp2.cur[point].x,
+                                                   dx );
 
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
@@ -5406,7 +5419,8 @@
               exc->iupx_called            &&
               exc->iupy_called            ) )
 #endif
-        exc->zp2.cur[point].y += dy;
+        exc->zp2.cur[point].y = OVERFLOW_ADD_LONG( exc->zp2.cur[point].y,
+                                                   dy );
 
       if ( touch )
         exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
@@ -5781,14 +5795,18 @@
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* subpixel hinting - make MSIRP respect CVT cut-in; */
-    if ( SUBPIXEL_HINTING_INFINALITY                         &&
-         exc->ignore_x_mode                                  &&
-         exc->GS.freeVector.x != 0                           &&
-         FT_ABS( distance - args[1] ) >= control_value_cutin )
+    if ( SUBPIXEL_HINTING_INFINALITY                                   &&
+         exc->ignore_x_mode                                            &&
+         exc->GS.freeVector.x != 0                                     &&
+         FT_ABS( OVERFLOW_SUB_LONG( distance,
+                                    args[1] ) ) >= control_value_cutin )
       distance = args[1];
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    exc->func_move( exc, &exc->zp1, point, args[1] - distance );
+    exc->func_move( exc,
+                    &exc->zp1,
+                    point,
+                    OVERFLOW_SUB_LONG( args[1], distance ) );
 
     exc->GS.rp1 = exc->GS.rp0;
     exc->GS.rp2 = point;