Commit e16bfbec4c63bff4e5218f180d822cadfd2c7f8c

Alexei Podtelezhnikov 2018-08-09T22:18:00

[raster, smooth] Reinstate bitmap size limits. This again moves outline and bitmap size checks one level up. * src/base/ftoutln.c (FT_Outline_Render): Explicitly reject enormous outlines. * src/raster/ftrend1.c (ft_raster1_render): Reject enormous bitmaps and, therefore, outlines that require them. * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto. * src/raster/ftraster.c (ft_black_render): Remove outline size checks. * src/smooth/ftgrays.c (gray_raster_render): Ditto. [STANDALONE]: Remove `FT_Outline_Get_CBox' copy.

diff --git a/ChangeLog b/ChangeLog
index 6a4ca57..9c0b012 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2018-08-09  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster, smooth] Reinstate bitmap size limits.
+
+	This again moves outline and bitmap size checks one level up.
+
+	* src/base/ftoutln.c (FT_Outline_Render): Explicitly reject enormous
+	outlines.
+	* src/raster/ftrend1.c (ft_raster1_render): Reject enormous bitmaps
+	and, therefore, outlines that require them.
+	* src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
+
+	* src/raster/ftraster.c (ft_black_render): Remove outline size checks.
+	* src/smooth/ftgrays.c (gray_raster_render): Ditto.
+	[STANDALONE]: Remove `FT_Outline_Get_CBox' copy.
+
 2018-08-08  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	[pcf] Revert massive unsigning.
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 09a6a1f..611b4f6 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -619,6 +619,7 @@
     FT_Error     error;
     FT_Renderer  renderer;
     FT_ListNode  node;
+    FT_BBox      cbox;
 
 
     if ( !library )
@@ -630,6 +631,11 @@
     if ( !params )
       return FT_THROW( Invalid_Argument );
 
+    FT_Outline_Get_CBox( outline, &cbox );
+    if ( cbox.xMin < -0x1000000L || cbox.yMin < -0x1000000L ||
+         cbox.xMax >  0x1000000L || cbox.yMax >  0x1000000L )
+      return FT_THROW( Invalid_Outline );
+
     renderer = library->cur_renderer;
     node     = library->renderers.head;
 
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index eece0f8..8a583ea 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -3251,7 +3251,6 @@
   {
     const FT_Outline*  outline    = (const FT_Outline*)params->source;
     const FT_Bitmap*   target_map = params->target;
-    FT_BBox            cbox;
 
     black_TWorker  worker[1];
 
@@ -3292,24 +3291,6 @@
     if ( !target_map->buffer )
       return FT_THROW( Invalid );
 
-    FT_Outline_Get_CBox( outline, &cbox );
-
-    /* reject too large outline coordinates */
-    if ( cbox.xMin < -0x1000000L || cbox.xMax > 0x1000000L ||
-         cbox.yMin < -0x1000000L || cbox.yMax > 0x1000000L )
-      return FT_THROW( Invalid );
-
-    /* truncate the bounding box to integer pixels */
-    cbox.xMin = cbox.xMin >> 6;
-    cbox.yMin = cbox.yMin >> 6;
-    cbox.xMax = ( cbox.xMax + 63 ) >> 6;
-    cbox.yMax = ( cbox.yMax + 63 ) >> 6;
-
-    /* reject too large glyphs */
-    if ( cbox.xMax - cbox.xMin > 0xFFFF ||
-         cbox.yMax - cbox.yMin > 0xFFFF )
-      return FT_THROW( Invalid );
-
     ras.outline = *outline;
     ras.target  = *target_map;
 
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 205cd9b..e8ea9cb 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -129,6 +129,14 @@
 
     ft_glyphslot_preset_bitmap( slot, mode, origin );
 
+    if ( bitmap->width > 0x7FFF || bitmap->rows > 0x7FFF )
+    {
+      FT_ERROR(( "ft_raster1_render: glyph is too large: %u x %u\n",
+                 bitmap->width, bitmap->rows ));
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
+    }
+
     /* allocate new one */
     if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
       goto Exit;
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index b6598aa..8f2a600 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -1611,83 +1611,6 @@ typedef ptrdiff_t  FT_PtrDist;
     return FT_THROW( Invalid_Outline );
   }
 
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   FT_Outline_Get_CBox
-   *
-   * @Description:
-   *   Return an outline's `control box'.  The control box encloses all
-   *   the outline's points, including Bézier control points.  Though it
-   *   coincides with the exact bounding box for most glyphs, it can be
-   *   slightly larger in some situations (like when rotating an outline
-   *   that contains Bézier outside arcs).
-   *
-   *   Computing the control box is very fast, while getting the bounding
-   *   box can take much more time as it needs to walk over all segments
-   *   and arcs in the outline.  To get the latter, you can use the
-   *   `ftbbox' component, which is dedicated to this single task.
-   *
-   * @Input:
-   *   outline ::
-   *     A pointer to the source outline descriptor.
-   *
-   * @Output:
-   *   acbox ::
-   *     The outline's control box.
-   *
-   * @Note:
-   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
-   */
-
-  static void
-  FT_Outline_Get_CBox( const FT_Outline*  outline,
-                       FT_BBox           *acbox )
-  {
-    TPos  xMin, yMin, xMax, yMax;
-
-
-    if ( outline && acbox )
-    {
-      if ( outline->n_points == 0 )
-      {
-        xMin = 0;
-        yMin = 0;
-        xMax = 0;
-        yMax = 0;
-      }
-      else
-      {
-        FT_Vector*  vec   = outline->points;
-        FT_Vector*  limit = vec + outline->n_points;
-
-
-        xMin = xMax = vec->x;
-        yMin = yMax = vec->y;
-        vec++;
-
-        for ( ; vec < limit; vec++ )
-        {
-          TPos  x, y;
-
-
-          x = vec->x;
-          if ( x < xMin ) xMin = x;
-          if ( x > xMax ) xMax = x;
-
-          y = vec->y;
-          if ( y < yMin ) yMin = y;
-          if ( y > yMax ) yMax = y;
-        }
-      }
-      acbox->xMin = xMin;
-      acbox->xMax = xMax;
-      acbox->yMin = yMin;
-      acbox->yMax = yMax;
-    }
-  }
-
 #endif /* STANDALONE_ */
 
 
@@ -1832,7 +1755,7 @@ typedef ptrdiff_t  FT_PtrDist;
   {
     const FT_Outline*  outline    = (const FT_Outline*)params->source;
     const FT_Bitmap*   target_map = params->target;
-    FT_BBox            cbox, clip;
+    FT_BBox            clip;
 
 #ifndef FT_STATIC_RASTER
     gray_TWorker  worker[1];
@@ -1895,26 +1818,11 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span_data = NULL;
     }
 
-    FT_Outline_Get_CBox( outline, &cbox );
-
-    /* reject too large outline coordinates */
-    if ( cbox.xMin < -0x1000000L || cbox.xMax > 0x1000000L ||
-         cbox.yMin < -0x1000000L || cbox.yMax > 0x1000000L )
-      return FT_THROW( Invalid_Outline );
-
-    /* truncate the bounding box to integer pixels */
-    cbox.xMin = cbox.xMin >> 6;
-    cbox.yMin = cbox.yMin >> 6;
-    cbox.xMax = ( cbox.xMax + 63 ) >> 6;
-    cbox.yMax = ( cbox.yMax + 63 ) >> 6;
-
-    /* reject too large glyphs */
-    if ( cbox.xMax - cbox.xMin > 0xFFFF ||
-         cbox.yMax - cbox.yMin > 0xFFFF )
-      return FT_THROW( Invalid_Outline );
-
     /* compute clipping box */
-    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
+    if ( params->flags & FT_RASTER_FLAG_DIRECT &&
+         params->flags & FT_RASTER_FLAG_CLIP   )
+      clip = params->clip_box;
+    else
     {
       /* compute clip box from target pixmap */
       clip.xMin = 0;
@@ -1922,21 +1830,12 @@ typedef ptrdiff_t  FT_PtrDist;
       clip.xMax = (FT_Pos)target_map->width;
       clip.yMax = (FT_Pos)target_map->rows;
     }
-    else if ( params->flags & FT_RASTER_FLAG_CLIP )
-      clip = params->clip_box;
-    else
-    {
-      clip.xMin = -32768L;
-      clip.yMin = -32768L;
-      clip.xMax =  32767L;
-      clip.yMax =  32767L;
-    }
 
     /* clip to target bitmap, exit if nothing to do */
-    ras.min_ex = FT_MAX( cbox.xMin, clip.xMin );
-    ras.min_ey = FT_MAX( cbox.yMin, clip.yMin );
-    ras.max_ex = FT_MIN( cbox.xMax, clip.xMax );
-    ras.max_ey = FT_MIN( cbox.yMax, clip.yMax );
+    ras.min_ex = clip.xMin;
+    ras.min_ey = clip.yMin;
+    ras.max_ex = clip.xMax;
+    ras.max_ey = clip.yMax;
 
     if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
       return 0;
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 1007f39..c6b7e21 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -147,6 +147,14 @@
 
     ft_glyphslot_preset_bitmap( slot, mode, origin );
 
+    if ( bitmap->width > 0x7FFF || bitmap->rows > 0x7FFF )
+    {
+      FT_ERROR(( "ft_smooth_render_generic: glyph is too large: %u x %u\n",
+                 bitmap->width, bitmap->rows ));
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
+    }
+
     /* allocate new one */
     if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
       goto Exit;