Commit e982f5b78a7d113a40e0c579cae7d96487e94216

suzuki toshiya 2015-09-21T23:07:22

[base] Check too long POST and sfnt resource (#45919). * src/base/ftbase.h (FT_MAC_RFORK_MAX_LEN): Maximum length of the resource fork for Mac OS. The resource fork larger than 16 MB can be written but could not be handled correctly, at least in Carbon routine. See https://support.microsoft.com/en-us/kb/130437 * src/base/ftobjs.c (Mac_Read_POST_Resource): No need `0x' for `%p' formatter. * src/base/ftbase.c (Mac_Read_POST_Resource): Check the fragment and total size of the concatenated POST resource before buffer allocation. (Mac_Read_sfnt_Resource): Check the declared size of sfnt resource before buffer allocation. * src/base/ftmac.c (read_lwfn, FT_New_Face_From_SFNT): Check the total resource size before buffer allocation.

diff --git a/ChangeLog b/ChangeLog
index 92b5b9b..c120afd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2015-09-21  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+	[base] Check too long POST and sfnt resource (#45919). 
+
+	* src/base/ftbase.h (FT_MAC_RFORK_MAX_LEN): Maximum length
+	of the resource fork for Mac OS.  The resource fork larger
+	than 16 MB can be written but could not be handled
+	correctly, at least in Carbon routine.
+	See https://support.microsoft.com/en-us/kb/130437
+
+	* src/base/ftobjs.c (Mac_Read_POST_Resource): No need `0x'
+	for `%p' formatter.
+
+	* src/base/ftbase.c (Mac_Read_POST_Resource): Check the
+	fragment and total size of the concatenated POST resource
+	before buffer allocation.
+	(Mac_Read_sfnt_Resource): Check the declared size of
+	sfnt resource before buffer allocation.
+
+	* src/base/ftmac.c (read_lwfn, FT_New_Face_From_SFNT):
+	Check the total resource size before buffer allocation.
+
 2015-09-19  Werner Lemberg  <wl@gnu.org>
 
 	[sfnt] Improve handling of invalid SFNT table entries (#45987).
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index cb57f96..0bd9e65 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -27,6 +27,11 @@
 FT_BEGIN_HEADER
 
 
+/* MacOS resource fork cannot exceed 16 MB at least for Carbon code */
+/* see https://support.microsoft.com/en-us/kb/130437                */
+#define FT_MAC_RFORK_MAX_LEN  0x00FFFFFFUL
+
+
   /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
   /* font, and try to load a face specified by the face_index.            */
   FT_LOCAL( FT_Error )
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
index 446a23a..8463190 100644
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -621,8 +621,8 @@
       total_size += GetHandleSize( post_data ) - 2;
       last_code = code;
 
-      /* detect integer overflows */
-      if ( total_size < old_total_size )
+      /* detect resource fork overflow */
+      if ( FT_MAC_RFORK_MAX_LEN < total_size )
       {
         error = FT_THROW( Array_Too_Large );
         goto Error;
@@ -747,6 +747,11 @@
       return FT_THROW( Invalid_Handle );
 
     sfnt_size = (FT_ULong)GetHandleSize( sfnt );
+
+    /* detect resource fork overflow */
+    if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
+      return FT_THROW( Array_Too_Large );
+
     if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
     {
       ReleaseResource( sfnt );
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 3a41ac0..b465a45 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1586,12 +1586,14 @@
       /* FT2 allocator takes signed long buffer length,
        * too large value causing overflow should be checked
        */
-      FT_TRACE4(( "                 POST fragment #%d: length=0x%08x\n",
-                  i, temp));
-      if ( 0x7FFFFFFFUL < temp || pfb_len + temp + 6 < pfb_len )
+      FT_TRACE4(( "                 POST fragment #%d: length=0x%08x"
+                  " total pfb_len=0x%08x\n",
+                  i, temp, pfb_len + temp + 6));
+      if ( FT_MAC_RFORK_MAX_LEN < temp               ||
+           FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 )
       {
-        FT_TRACE2(( "             too long fragment length makes"
-                    " pfb_len confused: temp=0x%08x\n", temp ));
+        FT_TRACE2(( "             MacOS resource length cannot exceed"
+                    " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
         error = FT_THROW( Invalid_Offset );
         goto Exit;
       }
@@ -1664,7 +1666,7 @@
       else
       {
         FT_TRACE3(( "    Write POST fragment #%d header (4-byte) to buffer"
-                    " 0x%p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
+                    " %p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
         if ( pfb_lenpos + 3 > pfb_len + 2 )
           goto Exit2;
         pfb_data[pfb_lenpos    ] = (FT_Byte)( len );
@@ -1676,7 +1678,7 @@
           break;
 
         FT_TRACE3(( "    Write POST fragment #%d header (6-byte) to buffer"
-                    " 0x%p + 0x%08x\n", i, pfb_data, pfb_pos ));
+                    " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
         if ( pfb_pos + 6 > pfb_len + 2 )
           goto Exit2;
         pfb_data[pfb_pos++] = 0x80;
@@ -1696,7 +1698,7 @@
         goto Exit2;
 
       FT_TRACE3(( "    Load POST fragment #%d (%d byte) to buffer"
-                  " 0x%p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
+                  " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
       if ( error )
         goto Exit2;
@@ -1774,6 +1776,8 @@
       goto Exit;
     if ( rlen == -1 )
       return FT_THROW( Cannot_Open_Resource );
+    if ( rlen > FT_MAC_RFORK_MAX_LEN )
+      return FT_THROW( Invalid_Offset );
 
     error = open_face_PS_from_sfnt_stream( library,
                                            stream,