[cairo-commit] 2 commits - src/cairo-type1-subset.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Apr 11 16:35:05 UTC 2021


 src/cairo-type1-subset.c |   26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

New commits:
commit 277a1daec80cb6cf7bfb0e200cf78e7842cb2f82
Merge: 26663cf3b 1484cfa55
Author: Heiko Lewin <hlewin at gmx.de>
Date:   Sun Apr 11 16:35:03 2021 +0000

    Merge branch 'type1_find_segments_bounds_check' into 'master'
    
    Fix out of bounds access in cairo_type1_font_subset_find_segments
    
    See merge request cairo/cairo!146

commit 1484cfa55146cf6c77f8ad60911f999ead0c12ff
Author: Uli Schlachter <psychon at znc.in>
Date:   Sun Apr 11 16:35:02 2021 +0000

    Fix out of bounds access in cairo_type1_font_subset_find_segments
    
    This function parses some raw font data and it trusts the font to be
    well-formed. This means that a font can just say "this segment is a
    gigabyte large" and the code will happily jump ahead in memory. Bad
    things then happen in practice.
    
    Fix this by adding lots of bounds check.
    
    Also, an existing bounds check makes sure we are still before the end of
    the data, but then happily reads the next six bytes. Fix this by making
    sure we actually have six bytes of data.
    
    No regression test since the last few times I tried to do this for font
    issues, I ended up with a large/huge blob of font data. Too large for
    the test suite.
    
    Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27969
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 2f04c8e10..a51e34f62 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -121,15 +121,15 @@ typedef struct _cairo_type1_font_subset {
     char *type1_end;
 
     char *header_segment;
-    int header_segment_size;
+    unsigned int header_segment_size;
     char *eexec_segment;
-    int eexec_segment_size;
+    unsigned int eexec_segment_size;
     cairo_bool_t eexec_segment_is_ascii;
 
     char *cleartext;
     char *cleartext_end;
 
-    int header_size;
+    unsigned int header_size;
 
     unsigned short eexec_key;
     cairo_bool_t hex_encode;
@@ -216,25 +216,31 @@ cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font)
 {
     unsigned char *p;
     const char *eexec_token;
-    int size, i;
+    unsigned int size, i;
 
     p = (unsigned char *) font->type1_data;
     font->type1_end = font->type1_data + font->type1_length;
-    if (p[0] == 0x80 && p[1] == 0x01) {
+    if (font->type1_length >= 2 && p[0] == 0x80 && p[1] == 0x01) {
+	if (font->type1_end < (char *)(p + 6))
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	font->header_segment_size =
-	    p[2] | (p[3] << 8) | (p[4] << 16) | ((uint32_t)p[5] << 24);
+	    p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
 	font->header_segment = (char *) p + 6;
 
 	p += 6 + font->header_segment_size;
+	if (font->type1_end < (char *)(p + 6))
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	font->eexec_segment_size =
-	    p[2] | (p[3] << 8) | (p[4] << 16) | ((uint32_t)p[5] << 24);
+	    p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
 	font->eexec_segment = (char *) p + 6;
 	font->eexec_segment_is_ascii = (p[1] == 1);
 
         p += 6 + font->eexec_segment_size;
-        while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) {
-            size = p[2] | (p[3] << 8) | (p[4] << 16) | ((uint32_t)p[5] << 24);
-            p += 6 + size;
+	while (font->type1_end >= (char *)(p + 6) && p[1] != 0x03) {
+	    size = p[2] | (p[3] << 8) | (p[4] << 16) | ((unsigned int) p[5] << 24);
+	    if (font->type1_end < (char *)(p + 6 + size))
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+	    p += 6 + size;
         }
         font->type1_end = (char *) p;
     } else {


More information about the cairo-commit mailing list