Commit 537c55d39d6636c93086780f03fba1f975a8299d

Dave Arnold 2014-10-02T06:32:32

[cff] Fix Savannah bug #43271. * src/cff/cf2font.c (cf2_computeDarkening): Change overflow detection to use logarithms and clamp `scaledStem'.

diff --git a/ChangeLog b/ChangeLog
index 1468429..aed1784 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-10-02  Dave Arnold  <darnold@adobe.com>
+
+	[cff] Fix Savannah bug #43271.
+
+	* src/cff/cf2font.c (cf2_computeDarkening): Change overflow
+	detection to use logarithms and clamp `scaledStem'.
+
 2014-10-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* src/base/ftcalc.c: Remove miscellaneous type casts.
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
index 6e99dc2..3d2c22a 100644
--- a/src/cff/cf2font.c
+++ b/src/cff/cf2font.c
@@ -105,6 +105,7 @@
     /* adjusting for emRatio converts darkenAmount to character */
     /* space (font units).                                      */
     CF2_Fixed  stemWidthPer1000, scaledStem;
+    FT_Int     logBase2;
 
 
     *darkenAmount = 0;
@@ -131,26 +132,33 @@
       /* convert from true character space to 1000 unit character space; */
       /* add synthetic emboldening effect                                */
 
-      /* we have to assure that the computation of `scaledStem' */
-      /* and `stemWidthPer1000' don't overflow                  */
+      /* `stemWidthPer1000' will not overflow for a legitimate font      */
 
       stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
 
-      if ( emRatio > CF2_FIXED_ONE                          &&
-           stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
-      {
-        stemWidthPer1000 = 0;                      /* to pacify compiler */
-        scaledStem       = cf2_intToFixed( x4 );
-      }
+      /* `scaledStem' can easily overflow, so we must clamp its maximum  */
+      /* value; the test doesn't need to be precise, but must be         */
+      /* conservative.  The clamp value (default 2333) where             */
+      /* `darkenAmount' is zero is well below the overflow value of      */
+      /* 32767.                                                          */
+      /*                                                                 */
+      /* FT_MSB computes the integer part of the base 2 logarithm.  The  */
+      /* number of bits for the product is 1 or 2 more than the sum of   */
+      /* logarithms; remembering that the 16 lowest bits of the fraction */
+      /* are dropped this is correct to within a factor of almost 4.     */
+      /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and   */
+      /* is flagged as possible overflow because 0xff.ffff * 0xff.ffff = */
+      /* 0xffff.fe00 is also 23+23.                                      */
+
+      logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
+                   FT_MSB( (FT_UInt32)ppem );
+
+      if ( logBase2 >= 46 )
+        /* possible overflow */
+        scaledStem = cf2_intToFixed( x4 );
       else
-      {
         scaledStem = FT_MulFix( stemWidthPer1000, ppem );
 
-        if ( ppem > CF2_FIXED_ONE           &&
-             scaledStem <= stemWidthPer1000 )
-          scaledStem = cf2_intToFixed( x4 );
-      }
-
       /* now apply the darkening parameters */
 
       if ( scaledStem < cf2_intToFixed( x1 ) )