Commit c13e75fb1b7f778b58bc2bc185e10a03f3cff001

David Turner 2006-02-27T13:14:42

* src/base/ftutil.c: ft_mem_alloc and related functions now return an error if a negative size is passed in parameters. * src/cache/ftccache.c: make ftc_node_destroy FT_BASE_DEF, it needs to be exported for rogue clients * src/pshinter/pshglob.c: prevent problems with malformed fonts which have an odd number of blue values (these are broken according to the specs). * src/cff/cffload.c, src/type1/t1load.c: modify the loaders to force even-ness of 'num_blue_values'. Also change the CFF loader so that invalid entries in index files are ignored.

diff --git a/ChangeLog b/ChangeLog
index abf7c38..a6dc576 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2006-02-27  David Turner  <david@freetype.org>
+
+    * src/base/ftutil.c: ft_mem_alloc and related functions now return an
+    error if a negative size is passed in parameters.
+
+    * src/cache/ftccache.c: make ftc_node_destroy FT_BASE_DEF, it needs to
+    be exported for rogue clients
+    
+    * src/pshinter/pshglob.c: prevent problems with malformed fonts which
+    have an odd number of blue values (these are broken according to the
+    specs).
+
+    * src/cff/cffload.c, src/type1/t1load.c: modify the loaders to force
+    even-ness of 'num_blue_values'. Also change the CFF loader so that
+    invalid entries in index files are ignored.
+
 2006-02-27  Chia-I Wu  <b90201047@ntu.edu.tw>
 
 	* src/base/ftobjs.c (FT_Set_Char_Size): Ahh.. forgot to check the case
diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index 31d3a1c..ddddd34 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -66,6 +66,11 @@
       else
         FT_MEM_ZERO( block, size );
     }
+    else if ( size < 0 )
+    {
+      /* may help catch/prevent nasty security issues */
+      error = FT_Err_Invalid_Argument;
+    }
 
     *p_error = error;
     return block;
@@ -87,6 +92,11 @@
       if ( block == NULL )
         error = FT_Err_Out_Of_Memory;
     }
+    else
+    {
+      /* may help catch/prevent security issues */
+      error = FT_Err_Invalid_Argument;
+    }
 
     *p_error = error;
     return block;
@@ -103,12 +113,16 @@
     FT_Error  error = FT_Err_Ok;
 
 
-    if ( size <= 0 )
+    if ( size < 0 || current < 0 )
+    {
+      error = FT_Err_Invalid_Argument;
+    }  
+    else if ( size == 0 )
     {
       ft_mem_free( memory, block );
       block = NULL;
     }
-    else if ( current <= 0 )
+    else if ( current == 0 )
     {
       FT_ASSERT( block == NULL );
 
@@ -145,12 +159,16 @@
     FT_Error  error = FT_Err_Ok;
 
 
-    if ( size <= 0 )
+    if ( size < 0 || current < 0 )
+    {
+      error = FT_Err_Invalid_Argument;
+    }
+    else if ( size == 0 )
     {
       ft_mem_free( memory, block );
       block = NULL;
     }
-    else if ( current <= 0 )
+    else if ( current == 0 )
     {
       FT_ASSERT( block == NULL );
 
@@ -190,7 +208,9 @@
   ft_mem_alloc( FT_Memory  memory,
                 FT_Long    size,
                 void*     *P )
-  {
+  { 
+    FT_Error  error = FT_Err_Ok;
+    
     FT_ASSERT( P != 0 );
 
     if ( size > 0 )
@@ -207,13 +227,17 @@
       FT_MEM_ZERO( *P, size );
     }
     else
+    {
       *P = NULL;
+      if ( size < 0 )
+        error = FT_Err_Invalid_Argument;
+    }
 
     FT_TRACE7(( "ft_mem_alloc:" ));
     FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
                 size, *P, P ));
 
-    return FT_Err_Ok;
+    return error;
   }
 
 
@@ -224,6 +248,8 @@
                  FT_Long    size,
                  void*     *P )
   {
+    FT_Error  error = FT_Err_Ok;
+    
     FT_ASSERT( P != 0 );
 
     if ( size > 0 )
@@ -239,13 +265,17 @@
       }
     }
     else
+    {
       *P = NULL;
+      if ( size < 0 )
+        error = FT_Err_Invalid_Argument;
+    }
 
     FT_TRACE7(( "ft_mem_qalloc:" ));
     FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
                 size, *P, P ));
 
-    return FT_Err_Ok;
+    return error;
   }
 
 
@@ -267,12 +297,15 @@
       return ft_mem_alloc( memory, size, P );
 
     /* if the new block if zero-sized, clear the current one */
-    if ( size <= 0 )
+    if ( size == 0 )
     {
       ft_mem_free( memory, P );
       return FT_Err_Ok;
     }
 
+    if ( size < 0 || current < 0 )
+      return FT_Err_Invalid_Argument;
+
     Q = memory->realloc( memory, current, size, *P );
     if ( !Q )
       goto Fail;
@@ -309,12 +342,15 @@
       return ft_mem_qalloc( memory, size, P );
 
     /* if the new block if zero-sized, clear the current one */
-    if ( size <= 0 )
+    if ( size == 0 )
     {
       ft_mem_free( memory, P );
       return FT_Err_Ok;
     }
 
+    if ( size < 0 || current < 0 )
+      return FT_Err_Invalid_Argument;
+
     Q = memory->realloc( memory, current, size, *P );
     if ( !Q )
       goto Fail;
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index 22ec06c..fd756fa 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -256,7 +256,8 @@
 
 
   /* remove a node from the cache manager */
-  FT_LOCAL_DEF( void )
+  /* this function is FT_BASE since it may be called by old rogue clients */
+  FT_BASE_DEF( void )
   ftc_node_destroy( FTC_Node     node,
                     FTC_Manager  manager )
   {
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 6d73e98..e576c3c 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -1235,7 +1235,7 @@
       }
 
       /* access element */
-      if ( off1 )
+      if ( off1 && off2 > off1 )
       {
         *pbyte_len = off2 - off1;
 
@@ -2011,7 +2011,7 @@
 
     if ( error )
       goto Exit;
-
+ 
     /* if it is a CID font, we stop there */
     if ( top->cid_registry != 0xFFFFU )
       goto Exit;
@@ -2040,6 +2040,9 @@
       FT_FRAME_EXIT();
       if ( error )
         goto Exit;
+
+      /* ensure that 'num_blue_values' is even */
+      priv->num_blue_values &= ~1;
     }
 
     /* read the local subrs, if any */
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 21d45e9..c02dc0b 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -150,7 +150,7 @@
     FT_UNUSED( target );
 
 
-    for ( ; read_count > 0; read_count -= 2 )
+    for ( ; read_count > 1; read_count -= 2 )
     {
       FT_Int         reference, delta;
       FT_UInt        count;
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 75c0e95..66c89a6 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -1989,6 +1989,9 @@
                         keyword_flags );
     if ( error )
       goto Exit;
+ 
+    /* ensure even-ness of 'num_blue_values' */
+    priv->num_blue_values &= ~1;
 
 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT