From ca4e707aa10782a0123011a54bd8c0d7da837b39 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Wed, 6 Jun 2018 08:18:23 +0200 Subject: [PATCH] [smooth, raster] Limit bitmap size (#54019). * src/raster/ftraster.c [STANDALONE] (FT_Outline_Get_CBox): Add function. [!STANDALONE]: Include FT_OUTLINE_H. (ft_black_render): Compute CBox and reject glyphs larger than 0xFFFF x 0xFFFF. * src/smooth/ftgrays.c (gray_raster_render): Reject glyphs larger than 0xFFFF x 0xFFFF. --- ChangeLog | 13 +++++ src/raster/ftraster.c | 114 ++++++++++++++++++++++++++++++++++++++---- src/smooth/ftgrays.c | 5 ++ 3 files changed, 122 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f4e2812a..048f85a3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2018-06-06 Werner Lemberg + + [smooth, raster] Limit bitmap size (#54019). + + * src/raster/ftraster.c [STANDALONE] (FT_Outline_Get_CBox): Add + function. + [!STANDALONE]: Include FT_OUTLINE_H. + (ft_black_render): Compute CBox and reject glyphs larger than + 0xFFFF x 0xFFFF. + + * src/smooth/ftgrays.c (gray_raster_render): Reject glyphs larger + than 0xFFFF x 0xFFFF. + 2018-06-03 Armin Hasitzka * src/smooth/ftgrays.c (gray_convert_glyph): Remove unused variables. diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c index e3da008d5..cc8fd5fed 100644 --- a/src/raster/ftraster.c +++ b/src/raster/ftraster.c @@ -65,6 +65,7 @@ #include #include "ftraster.h" #include FT_INTERNAL_CALC_H /* for FT_MulDiv and FT_MulDiv_No_Round */ +#include FT_OUTLINE_H /* for FT_Outline_Get_CBox */ #endif /* !STANDALONE_ */ @@ -2925,6 +2926,94 @@ } +#ifdef STANDALONE_ + + /************************************************************************** + * + * The following functions should only compile in stand-alone mode, + * i.e., when building this component without the rest of FreeType. + * + */ + + /************************************************************************** + * + * @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 ) + { + Long 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++ ) + { + Long 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_ */ + + /************************************************************************** * * @Function: @@ -3183,6 +3272,7 @@ { const FT_Outline* outline = (const FT_Outline*)params->source; const FT_Bitmap* target_map = params->target; + FT_BBox cbox; black_TWorker worker[1]; @@ -3223,19 +3313,23 @@ if ( !target_map->buffer ) return FT_THROW( Invalid ); + FT_Outline_Get_CBox( outline, &cbox ); + /* reject too large outline coordinates */ - { - FT_Vector* vec = outline->points; - FT_Vector* limit = vec + outline->n_points; + 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; - for ( ; vec < limit; vec++ ) - { - if ( vec->x < -0x1000000L || vec->x > 0x1000000L || - vec->y < -0x1000000L || vec->y > 0x1000000L ) - return FT_THROW( Invalid ); - } - } + /* 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/smooth/ftgrays.c b/src/smooth/ftgrays.c index 10fdddf76..138538080 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -1899,6 +1899,11 @@ typedef ptrdiff_t FT_PtrDist; 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 ) ) {