Cherry-pick https://gitlab.freedesktop.org/cairo/cairo/-/commit/277a1daec80cb6cf7bfb0e200cf78e7842cb2f82 draft
authorJonathan Kew <jkew@mozilla.com>
Wed, 14 Apr 2021 13:27:01 +0100
changeset 3667302 6b67f2bade3aac7f77904b719ba1f226f12df48a
parent 3667301 37a494ea546fa48f0e4ecf0a05edf8a4724e6fc6
child 3667303 dcfa64c1b9a07e32389ac627848dbdf26355095a
push id683063
push userjkew@mozilla.com
push dateMon, 19 Apr 2021 13:15:26 +0000
treeherdertry@919daaf50d14 [default view] [failures only]
milestone89.0a1
Cherry-pick https://gitlab.freedesktop.org/cairo/cairo/-/commit/277a1daec80cb6cf7bfb0e200cf78e7842cb2f82 Fix out of bounds access in cairo_type1_font_subset_find_segments
gfx/cairo/cairo/src/cairo-type1-subset.c
--- a/gfx/cairo/cairo/src/cairo-type1-subset.c
+++ b/gfx/cairo/cairo/src/cairo-type1-subset.c
@@ -116,25 +116,25 @@ typedef struct _cairo_type1_font_subset 
 
     int lenIV;
 
     char *type1_data;
     unsigned int type1_length;
     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;
     int hex_column;
 
     struct {
 	double stack[TYPE1_STACKSIZE];
 	int sp;
@@ -211,35 +211,41 @@ find_token (const char *buffer, const ch
     return NULL;
 }
 
 static cairo_status_t
 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 {
 	eexec_token = find_token ((char *) p, font->type1_end, "eexec");
 	if (eexec_token == NULL)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
 	font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");