Commit 4404ec4ef5b8dfc7edcd92bada5e5e4bcbc9a81a

Werner Lemberg 2012-10-19T09:06:53

[cff] Fix more value errors and improve tracing. * src/cff/cffparse.c (cff_parse_integer): Emit tracing message in case of error. (cff_parse_real): Handle and trace overflow, underflow, and bad data consistently. (do_fixed): New helper function, handling and tracing overflow. (cff_parse_fixed, cff_parse_fixed_scaled): Use `do_fixed'.

diff --git a/ChangeLog b/ChangeLog
index d9fb1a6..682b7c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-10-19  Werner Lemberg  <wl@gnu.org>
+
+	[cff] Fix more value errors and improve tracing.
+
+	* src/cff/cffparse.c (cff_parse_integer): Emit tracing message in
+	case of error.
+	(cff_parse_real): Handle and trace overflow, underflow, and bad data
+	consistently.
+	(do_fixed): New helper function, handling and tracing overflow.
+	(cff_parse_fixed, cff_parse_fixed_scaled): Use `do_fixed'.
+
 2012-10-17  Werner Lemberg  <wl@gnu.org>
 
 	[psaux] Fix some value overflows.
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 2e93bd3..015a1d1 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -105,6 +105,7 @@
 
   Bad:
     val = 0;
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
     goto Exit;
   }
 
@@ -165,7 +166,7 @@
 
         /* Make sure we don't read past the end. */
         if ( p >= limit )
-          goto Exit;
+          goto Bad;
       }
 
       /* Get the nibble. */
@@ -202,7 +203,7 @@
 
           /* Make sure we don't read past the end. */
           if ( p >= limit )
-            goto Exit;
+            goto Bad;
         }
 
         /* Get the nibble. */
@@ -241,7 +242,7 @@
 
           /* Make sure we don't read past the end. */
           if ( p >= limit )
-            goto Exit;
+            goto Bad;
         }
 
         /* Get the nibble. */
@@ -254,13 +255,21 @@
 
         /* Arbitrarily limit exponent. */
         if ( exponent > 1000 )
-          goto Exit;
+        {
+          if ( exponent_sign )
+            goto Underflow;
+          else
+            goto Overflow;
+        }
       }
 
       if ( exponent_sign )
         exponent = -exponent;
     }
 
+    if ( !number )
+      goto Exit;
+
     /* We don't check `power_ten' and `exponent_add'. */
     exponent += power_ten + exponent_add;
 
@@ -329,7 +338,7 @@
 
       /* Check for overflow and underflow. */
       if ( FT_ABS( integer_length ) > 5 )
-        goto Exit;
+        goto Overflow;
 
       /* Remove non-significant digits. */
       if ( integer_length < 0 )
@@ -358,17 +367,32 @@
         number *= power_tens[-fraction_length];
 
         if ( number > 0x7FFFL )
-          goto Exit;
+          goto Overflow;
 
         result = number << 16;
       }
     }
 
+  Exit:
     if ( sign )
       result = -result;
 
-  Exit:
     return result;
+
+  Overflow:
+    result = 0x7FFFFFFFL;
+    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+    goto Exit;
+
+  Underflow:
+    result = 0;
+    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
+    goto Exit;
+
+  Bad:
+    result = 0;
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
+    goto Exit;
   }
 
 
@@ -383,36 +407,57 @@
 
   /* read a floating point number, either integer or real */
   static FT_Fixed
-  cff_parse_fixed( FT_Byte**  d )
-  {
-    return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL )
-                     : cff_parse_integer( d[0], d[1] ) << 16;
-  }
-
-
-  /* read a floating point number, either integer or real, */
-  /* but return `10^scaling' times the number read in      */
-  static FT_Fixed
-  cff_parse_fixed_scaled( FT_Byte**  d,
-                          FT_Long    scaling )
+  do_fixed( FT_Byte**  d,
+            FT_Long    scaling )
   {
     if ( **d == 30 )
       return cff_parse_real( d[0], d[1], scaling, NULL );
     else
     {
-      FT_Long  val = cff_parse_integer( d[0], d[1] ) * power_tens[scaling];
+      FT_Long  val = cff_parse_integer( d[0], d[1] );
+
 
+      if ( scaling )
+        val *= power_tens[scaling];
 
       if ( val > 0x7FFF )
-        return 0x7FFFFFFFL;
+      {
+        val = 0x7FFFFFFFL;
+        goto Overflow;
+      }
       else if ( val < -0x7FFF )
-        return -0x7FFFFFFFL;
+      {
+        val = -0x7FFFFFFFL;
+        goto Overflow;
+      }
 
       return val << 16;
+
+    Overflow:
+      FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+      return val;
     }
   }
 
 
+  /* read a floating point number, either integer or real */
+  static FT_Fixed
+  cff_parse_fixed( FT_Byte**  d )
+  {
+    return do_fixed( d, 0 );
+  }
+
+
+  /* read a floating point number, either integer or real, */
+  /* but return `10^scaling' times the number read in      */
+  static FT_Fixed
+  cff_parse_fixed_scaled( FT_Byte**  d,
+                          FT_Long    scaling )
+  {
+    return do_fixed( d, scaling );
+  }
+
+
   /* read a floating point number, either integer or real,     */
   /* and return it as precise as possible -- `scaling' returns */
   /* the scaling factor (as a power of 10)                     */