Commit e866cf3f5537cfb03cfb87e3e607f13f41f5d299

suzuki toshiya 2009-08-01T00:32:06

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

diff --git a/ChangeLog b/ChangeLog
index 38ad799..699070a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,63 @@
 2009-07-31  suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
 
+	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 <mpsuzuki@hiroshima-u.ac.jp>
+
 	psaux: Prevent invalid arguments to afm_parser_read_vals().
 
 	* src/psaux/afmparse.c (afm_parser_read_vals): Change
diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index ce5557a..30ec14e 100644
--- 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
 
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index 30eb655..fa12f31 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -37,6 +37,7 @@ FT_TRACE_DEF( raster )    /* monochrome rasterizer   (ftraster.c) */
 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.) */
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 8810cfa..46fcce6 100644
--- 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;
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index 82fc4e6..3892fab 100644
--- 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;
   }
 
 
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index 443d272..326d8e7 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -18,12 +18,22 @@
 
 #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
 
 
   /*************************************************************************/
+  /*                                                                       */
+  /* 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 );
   }
 
 
diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c
index 1894408..631ec46 100644
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -485,7 +485,12 @@ THE SOFTWARE.
           (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 @@ THE SOFTWARE.
 
     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                         */
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 129a57c..217adf2 100644
--- 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:
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 9b9a6a5..57cfdc8 100644
--- 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;
     }
 
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index 546ea3b..df92e9a 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -130,7 +130,7 @@ FT_BEGIN_HEADER
     /* 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;
diff --git a/src/pfr/pfrsbit.c b/src/pfr/pfrsbit.c
index 45ff666..8a38bec 100644
--- 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 */
         {
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index b5530f7..efb438b 100644
--- 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;
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index a47c97a..3d3d30a 100644
--- 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 )