shithub: freetype+ttf2subf

Download patch

ref: e866cf3f5537cfb03cfb87e3e607f13f41f5d299
parent: d3ed6d1bba27aaae4774db957a82caa6d5b67632
author: suzuki toshiya <[email protected]>
date: Fri Jul 31 20:32:06 EDT 2009

Improve bitmap size or pixel variables for 16-bit systems.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,63 @@
 2009-07-31  suzuki toshiya <[email protected]>
 
+	Improve bitmap size or pixel variables for 16-bit systems.
+
+	* include/freetype/config/ftstdlib.h: Introduce
+	FT_INT_MIN, to use in signed integer overflow in
+	16-bit and 64-bit platforms.
+	
+	* include/freetype/internal/fttrace.h: Add a tracer
+	to ftsynth.c.
+	
+	* src/base/ftbitmap.c (FT_Bitmap_Embolden): Check
+	invalid strength causing integer overflow on 16-bit
+	platform.
+	
+	* src/base/ftcalc.c (ft_corner_orientation): Change
+	the internal calculation from FT_Int to FT_Long, to
+	avoid an overflow on 16-bit platforms.  The caller of
+	this function should use only the sign of result,
+	so the cast to FT_Int is acceptable.
+	
+	* src/base/ftsynth.c: Introduce a tracer for synth module.
+	(FT_GlyphSlot_Embolden): Check invalid strength causing
+	integer overflow on 16-bit platform.
+	
+	* src/bdf/bdfdrivr.c (BDF_Face_Init): The glyph index
+	in FT2 API is typed as FT_UInt, although BDF driver
+	can handle unsigned long glyph index internally.  To
+	avoid integer overflow on 16-bit platform, too large
+	glyph index should be excluded.
+	(BDF_Glyph_Load): The glyph pitch in FT2 is typed as
+	FT_UInt, although BDF driver can handle unsigned long
+	glyph pitch internally.  To avoid integer overflow on
+	16-bit platform, too large glyph pitch should not be
+	returned.
+	
+	* src/pfr/pfrsbit.c (pfr_slot_load_bitmap): The glyph
+	pitch in FT2 is typed as FT_UInt, although PFR font
+	format can include huge bitmap glyph with 24-bit pitch
+	(however, a glyph spends 16.7 pixel, it's not realistic).
+	To avoid integer overflow on 16-bit platform, huge
+	bitmap glyph should be excluded.
+	
+	* src/smooth/ftgrays.c (gray_hline): As FT_Span.x is
+	truncated to fit its type (16-bit short), FT_Span.y
+	should be truncated to fit its type (FT_Int).
+	
+	* src/cff/cffdrivr.c (cff_get_ros): CFF specification
+	defines the supplement in ROS as a real number.
+	Truncate it to fit public FT2 API.
+	
+	* src/cff/cffparse.c (cff_parse_cid_ros): Warn the
+	supplement if it is truncated or rounded in cff_get_ros().
+	
+	* src/cff/cfftypes.h: Change the type of internal variable
+	`supplement' from FT_Long to FT_ULong to fit the signedness
+	to the type in public API.
+
+2009-07-31  suzuki toshiya <[email protected]>
+
 	psaux: Prevent invalid arguments to afm_parser_read_vals().
 
 	* src/psaux/afmparse.c (afm_parser_read_vals): Change
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -61,6 +61,7 @@
 
 #define FT_CHAR_BIT   CHAR_BIT
 #define FT_INT_MAX    INT_MAX
+#define FT_INT_MIN    INT_MIN
 #define FT_UINT_MAX   UINT_MAX
 #define FT_ULONG_MAX  ULONG_MAX
 
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -37,6 +37,7 @@
 FT_TRACE_DEF( smooth )    /* anti-aliasing raster    (ftgrays.c)  */
 FT_TRACE_DEF( mm )        /* MM interface            (ftmm.c)     */
 FT_TRACE_DEF( raccess )   /* resource fork accessor  (ftrfork.c)  */
+FT_TRACE_DEF( synth )     /* bold/slant synthesizer  (ftsynth.c)  */
 
   /* Cache sub-system */
 FT_TRACE_DEF( cache )     /* cache sub-system        (ftcache.c, etc.) */
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -228,8 +228,12 @@
     if ( !bitmap || !bitmap->buffer )
       return FT_Err_Invalid_Argument;
 
-    xstr = FT_PIX_ROUND( xStrength ) >> 6;
-    ystr = FT_PIX_ROUND( yStrength ) >> 6;
+    if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
+         ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
+      return FT_Err_Invalid_Argument;
+       
+    xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
+    ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
 
     if ( xstr == 0 && ystr == 0 )
       return FT_Err_Ok;
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -842,7 +842,7 @@
                          FT_Pos  out_x,
                          FT_Pos  out_y )
   {
-    FT_Int  result;
+    FT_Long  result; /* avoid overflow on 16-bit system */
 
 
     /* deal with the trivial cases quickly */
@@ -909,7 +909,8 @@
 #endif
     }
 
-    return result;
+    /* XXX: only the sign of return value, +1/0/-1 must be used */
+    return (FT_Int)result;
   }
 
 
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -18,6 +18,7 @@
 
 #include <ft2build.h>
 #include FT_SYNTHESIS_H
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_OUTLINE_H
 #include FT_BITMAP_H
@@ -24,7 +25,16 @@
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_synth
+
   /*************************************************************************/
+  /*************************************************************************/
   /****                                                                 ****/
   /****   EXPERIMENTAL OBLIQUING SUPPORT                                ****/
   /****                                                                 ****/
@@ -106,6 +116,18 @@
         xstr = 1 << 6;
       ystr &= ~63;
 
+      /*
+       * XXX: overflow check for 16-bit system, for compatibility
+       *      with FT_GlyphSlot_Embolden() since freetype-2.1.10.
+       *      unfortunately, this function return no informations
+       *      about the cause of error.
+       */
+      if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )
+      {
+        FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));
+        FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr ));
+        return;
+      }
       error = FT_GlyphSlot_Own_Bitmap( slot );
       if ( error )
         return;
@@ -129,8 +151,9 @@
     slot->metrics.vertBearingY += ystr;
     slot->metrics.vertAdvance  += ystr;
 
+    /* XXX: 16-bit overflow case must be excluded before here */
     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
-      slot->bitmap_top += ystr >> 6;
+      slot->bitmap_top += (FT_Int)( ystr >> 6 );
   }
 
 
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -485,7 +485,12 @@
           (face->en_table[n]).glyph = (FT_Short)n;
 
           if ( cur[n].encoding == font->default_char )
-            face->default_glyph = n;
+          {
+            if ( n < FT_UINT_MAX )
+              face->default_glyph = (FT_UInt)n;
+            else
+              FT_TRACE1(( "idx %d is too large for this system\n", n ));
+          }
         }
       }
 
@@ -677,7 +682,10 @@
 
     bitmap->rows  = glyph.bbx.height;
     bitmap->width = glyph.bbx.width;
-    bitmap->pitch = glyph.bpr;
+    if ( glyph.bpr > INT_MAX )
+      FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
+                   glyph.bpr ));
+    bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
 
     /* note: we don't allocate a new array to hold the bitmap; */
     /*       we can simply point to it                         */
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -495,8 +495,19 @@
         *ordering = cff->ordering;
       }
 
+      /*
+       * XXX: According to Adobe TechNote #5176, the supplement in CFF
+       *      can be a real number. We truncate it to fit public API
+       *      since freetype-2.3.6.
+       */
       if ( supplement )
-        *supplement = dict->cid_supplement;
+      {
+        if ( dict->cid_supplement < FT_INT_MIN ||
+             dict->cid_supplement > FT_INT_MAX )
+          FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
+                      dict->cid_supplement ));
+        *supplement = (FT_Int)dict->cid_supplement;
+      }
     }
       
   Fail:
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -554,7 +554,12 @@
     {
       dict->cid_registry   = (FT_UInt)cff_parse_num ( data++ );
       dict->cid_ordering   = (FT_UInt)cff_parse_num ( data++ );
-      dict->cid_supplement = (FT_ULong)cff_parse_num( data );
+      if ( **data == 30 )
+        FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
+      dict->cid_supplement = cff_parse_num( data );
+      if ( dict->cid_supplement < 0 )
+        FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
+                   dict->cid_supplement ));
       error = CFF_Err_Ok;
     }
 
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -130,7 +130,7 @@
     /* these should only be used for the top-level font dictionary */
     FT_UInt    cid_registry;
     FT_UInt    cid_ordering;
-    FT_ULong   cid_supplement;
+    FT_Long    cid_supplement;
 
     FT_Long    cid_font_version;
     FT_Long    cid_font_revision;
--- a/src/pfr/pfrsbit.c
+++ b/src/pfr/pfrsbit.c
@@ -630,18 +630,35 @@
                                        &xpos, &ypos,
                                        &xsize, &ysize,
                                        &advance, &format );
+
+      /*
+       * XXX: on 16bit system, we return an error for huge bitmap
+       *      which causes a size truncation, because truncated
+       *      size properties makes bitmap glyph broken.
+       */
+      if ( xpos > FT_INT_MAX || ( ypos + ysize ) > FT_INT_MAX )
+      {
+        FT_TRACE1(( "pfr_slot_load_bitmap:" ));
+        FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",
+                     xpos, ypos ));
+        error = PFR_Err_Invalid_Pixel_Size;
+      }
+
       if ( !error )
       {
         glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
 
         /* Set up glyph bitmap and metrics */
+
+        /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */
         glyph->root.bitmap.width      = (FT_Int)xsize;
         glyph->root.bitmap.rows       = (FT_Int)ysize;
-        glyph->root.bitmap.pitch      = (FT_Long)( xsize + 7 ) >> 3;
+        glyph->root.bitmap.pitch      = (FT_Int)( xsize + 7 ) >> 3;
         glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
 
-        glyph->root.metrics.width        = (FT_Long)xsize << 6;
-        glyph->root.metrics.height       = (FT_Long)ysize << 6;
+        /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */
+        glyph->root.metrics.width        = (FT_Pos)xsize << 6;
+        glyph->root.metrics.height       = (FT_Pos)ysize << 6;
         glyph->root.metrics.horiBearingX = xpos << 6;
         glyph->root.metrics.horiBearingY = ypos << 6;
         glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
@@ -649,8 +666,9 @@
         glyph->root.metrics.vertBearingY = 0;
         glyph->root.metrics.vertAdvance  = size->root.metrics.height;
 
-        glyph->root.bitmap_left = xpos;
-        glyph->root.bitmap_top  = ypos + ysize;
+        /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */
+        glyph->root.bitmap_left = (FT_Int)xpos;
+        glyph->root.bitmap_top  = (FT_Int)(ypos + ysize);
 
         /* Allocate and read bitmap data */
         {
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -1271,6 +1271,10 @@
     if ( x >= 32767 )
       x = 32767;
 
+    /* FT_Span.y is an integer, so limit our coordinates appropriately */
+    if ( y >= FT_INT_MAX )
+      y = FT_INT_MAX;
+
     if ( coverage )
     {
       /* see whether we can add this span to the current list */
@@ -1309,7 +1313,7 @@
 #endif /* FT_DEBUG_LEVEL_TRACE */
 
         ras.num_gray_spans = 0;
-        ras.span_y         = y;
+        ras.span_y         = (int)y;
 
         count = 0;
         span  = ras.gray_spans;
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -321,12 +321,19 @@
 
     FT_Outline_Translate( outline, x_shift, y_shift );
 
+    /*
+     * XXX: on 16bit system, we return an error for huge bitmap
+     * to prevent an overflow.
+     */
+    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
+      return Smooth_Err_Invalid_Pixel_Size;
+
     if ( error )
       goto Exit;
 
     slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = x_left;
-    slot->bitmap_top  = y_top;
+    slot->bitmap_left = (FT_Int)x_left;
+    slot->bitmap_top  = (FT_Int)y_top;
 
   Exit:
     if ( outline && origin )