Commit 88ab638e0fd4cdc5cdb40d5dc0897ec064ce9719

Werner Lemberg 2007-06-07T05:01:56

* src/sfnt/ttsbit0.c (tt_sbit_decoder_init, tt_sbit_decoder_load_image): Protect against integer overflows. * src/pfr/pfrgload.c (pfr_glyph_load_simple): More bounding checks for `x_control' and `y_control'.

diff --git a/ChangeLog b/ChangeLog
index c26bf5e..911ebc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-06-07  Werner Lemberg  <wl@gnu.org>
+
+	* src/sfnt/ttsbit0.c (tt_sbit_decoder_init,
+	tt_sbit_decoder_load_image): Protect against integer overflows.
+
+
+	* src/pfr/pfrgload.c (pfr_glyph_load_simple): More bounding checks
+	for `x_control' and `y_control'.
+
 2007-06-06  Werner Lemberg  <wl@gnu.org>
 
 	* src/base/ftoutln.c (FT_Outline_Decompose): Check `last'.
diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c
index d92c30a..3bb1733 100644
--- a/src/pfr/pfrgload.c
+++ b/src/pfr/pfrgload.c
@@ -354,14 +354,15 @@
 
       for (;;)
       {
-        FT_Int  format, args_format = 0, args_count, n;
+        FT_UInt  format, format_low, args_format = 0, args_count, n;
 
 
         /***************************************************************/
         /*  read instruction                                           */
         /*                                                             */
         PFR_CHECK( 1 );
-        format = PFR_NEXT_BYTE( p );
+        format     = PFR_NEXT_BYTE( p );
+        format_low = format & 15;
 
         switch ( format >> 4 )
         {
@@ -381,30 +382,34 @@
         case 5:                             /* move to outside contour */
           FT_TRACE6(( "- move to outside" ));
         Line1:
-          args_format = format & 15;
+          args_format = format_low;
           args_count  = 1;
           break;
 
         case 2:                             /* horizontal line to */
-          FT_TRACE6(( "- horizontal line to cx.%d", format & 15 ));
+          FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
+          if ( format_low > x_count )
+            goto Failure;
+          pos[0].x   = glyph->x_control[format_low];
           pos[0].y   = pos[3].y;
-          pos[0].x   = glyph->x_control[format & 15];
           pos[3]     = pos[0];
           args_count = 0;
           break;
 
         case 3:                             /* vertical line to */
-          FT_TRACE6(( "- vertical line to cy.%d", format & 15 ));
+          FT_TRACE6(( "- vertical line to cy.%d", format_low ));
+          if ( format_low > y_count )
+            goto Failure;
           pos[0].x   = pos[3].x;
-          pos[0].y   = glyph->y_control[format & 15];
-          pos[3] = pos[0];
+          pos[0].y   = glyph->y_control[format_low];
+          pos[3]     = pos[0];
           args_count = 0;
           break;
 
         case 6:                             /* horizontal to vertical curve */
           FT_TRACE6(( "- hv curve " ));
-          args_format  = 0xB8E;
-          args_count   = 3;
+          args_format = 0xB8E;
+          args_count  = 3;
           break;
 
         case 7:                             /* vertical to horizontal curve */
@@ -416,7 +421,7 @@
         default:                            /* general curve to */
           FT_TRACE6(( "- general curve" ));
           args_count  = 4;
-          args_format = format & 15;
+          args_format = format_low;
         }
 
         /***********************************************************/
diff --git a/src/sfnt/ttsbit0.c b/src/sfnt/ttsbit0.c
index edbfa10..f8adc64 100644
--- a/src/sfnt/ttsbit0.c
+++ b/src/sfnt/ttsbit0.c
@@ -235,7 +235,7 @@
                         TT_SBit_MetricsRec*  metrics )
   {
     FT_Error   error;
-    FT_Stream  stream     = face->root.stream;
+    FT_Stream  stream = face->root.stream;
     FT_ULong   ebdt_size;
 
 
@@ -261,14 +261,27 @@
 
     /* now find the strike corresponding to the index */
     {
-      FT_Byte*  p = decoder->eblc_base + 8 + 48 * strike_index;
+      FT_Byte*  p;
+
 
+      if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
+      {
+        error = SFNT_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      p = decoder->eblc_base + 8 + 48 * strike_index;
 
       decoder->strike_index_array = FT_NEXT_ULONG( p );
       p                          += 4;
       decoder->strike_index_count = FT_NEXT_ULONG( p );
       p                          += 34;
       decoder->bit_depth          = *p;
+
+      if ( decoder->strike_index_array > face->sbit_table_size             ||
+           decoder->strike_index_array + 8 * decoder->strike_index_count >
+             face->sbit_table_size                                         )
+        error = SFNT_Err_Invalid_File_Format;
     }
 
   Exit:
@@ -642,9 +655,9 @@
 
     for ( nn = 0; nn < num_components; nn++ )
     {
-      FT_UInt   gindex = FT_NEXT_USHORT( p );
-      FT_Byte   dx     = FT_NEXT_BYTE( p );
-      FT_Byte   dy     = FT_NEXT_BYTE( p );
+      FT_UInt  gindex = FT_NEXT_USHORT( p );
+      FT_Byte  dx     = FT_NEXT_BYTE( p );
+      FT_Byte  dy     = FT_NEXT_BYTE( p );
 
 
       /* NB: a recursive call */
@@ -775,9 +788,6 @@
     FT_ULong  image_start = 0, image_end = 0, image_offset;
 
 
-    if ( p + 8 * num_ranges > p_limit )
-      goto NoBitmap;
-
     for ( ; num_ranges > 0; num_ranges-- )
     {
       start = FT_NEXT_USHORT( p );
@@ -792,6 +802,12 @@
 
   FoundRange:
     image_offset = FT_NEXT_ULONG( p );
+
+    /* overflow check */
+    if ( decoder->eblc_base + decoder->strike_index_array + image_offset <
+           decoder->eblc_base )
+      goto Failure;
+
     p = decoder->eblc_base + decoder->strike_index_array + image_offset;
     if ( p + 8 > p_limit )
       goto NoBitmap;
@@ -831,7 +847,7 @@
           goto NoBitmap;
 
         image_start = image_size * ( glyph_index - start );
-        image_end   = image_start  + image_size;
+        image_end   = image_start + image_size;
       }
       break;
 
@@ -858,6 +874,11 @@
           goto NoBitmap;
 
         num_glyphs = FT_NEXT_ULONG( p );
+
+        /* overflow check */
+        if ( p + ( num_glyphs + 1 ) * 4 < p )
+          goto Failure;
+
         if ( p + ( num_glyphs + 1 ) * 4 > p_limit )
           goto NoBitmap;
 
@@ -895,6 +916,11 @@
           goto NoBitmap;
 
         num_glyphs = FT_NEXT_ULONG( p );
+
+        /* overflow check */
+        if ( p + 2 * num_glyphs < p )
+          goto Failure;
+
         if ( p + 2 * num_glyphs > p_limit )
           goto NoBitmap;
 
@@ -910,7 +936,7 @@
         if ( mm >= num_glyphs )
           goto NoBitmap;
 
-        image_start = image_size*mm;
+        image_start = image_size * mm;
         image_end   = image_start + image_size;
       }
       break;
@@ -932,6 +958,9 @@
                                         x_pos,
                                         y_pos );
 
+  Failure:
+    return SFNT_Err_Invalid_Table;
+
   NoBitmap:
     return SFNT_Err_Invalid_Argument;
   }