summaryrefslogtreecommitdiff
path: root/gnu/packages/patches/libwebp-CVE-2016-9085.patch
blob: e40b3533034bb5fa169d8be0f0c224fdd99127a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
Fix CVE-2016-9085 (several integer overflows):

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9085
http://seclists.org/oss-sec/2016/q4/253

Patch copied from upstream source repository:

https://chromium.googlesource.com/webm/libwebp/+/e2affacc35f1df6cc3b1a9fa0ceff5ce2d0cce83

From e2affacc35f1df6cc3b1a9fa0ceff5ce2d0cce83 Mon Sep 17 00:00:00 2001
From: Pascal Massimino <pascal.massimino@gmail.com>
Date: Mon, 10 Oct 2016 11:48:39 +0200
Subject: [PATCH] fix potential overflow when width * height * 4 >= (1<<32)

Mostly: avoid doing calculation like: ptr + j * stride
when stride is 'int'. Rather use size_t, or pointer increments (ptr += stride)
when possible.

BUG=webp:314

Change-Id: I81c684b515dd1ec4f601f32d50a6e821c4e46e20
---
 examples/gifdec.c | 56 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 24 deletions(-)

diff --git a/examples/gifdec.c b/examples/gifdec.c
index 83c3d82..7df176f 100644
--- a/examples/gifdec.c
+++ b/examples/gifdec.c
@@ -20,6 +20,7 @@
 
 #include "webp/encode.h"
 #include "webp/mux_types.h"
+#include "webp/format_constants.h"
 
 #define GIF_TRANSPARENT_COLOR 0x00000000
 #define GIF_WHITE_COLOR       0xffffffff
@@ -103,12 +104,19 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
   const GifImageDesc* const image_desc = &gif->Image;
   uint32_t* dst = NULL;
   uint8_t* tmp = NULL;
-  int ok = 0;
-  GIFFrameRect rect = {
+  const GIFFrameRect rect = {
       image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
   };
+  const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
+  int ok = 0;
   *gif_rect = rect;
 
+  if (memory_needed != (size_t)memory_needed ||
+      memory_needed > 4 * MAX_IMAGE_AREA) {
+    fprintf(stderr, "Image is too large (%d x %d).", rect.width, rect.height);
+    return 0;
+  }
+
   // Use a view for the sub-picture:
   if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
                        rect.width, rect.height, &sub_image)) {
@@ -132,15 +140,15 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
            y += interlace_jumps[pass]) {
         if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
         Remap(gif, tmp, rect.width, transparent_index,
-              dst + y * sub_image.argb_stride);
+              dst + y * (size_t)sub_image.argb_stride);
       }
     }
   } else {  // Non-interlaced image.
     int y;
-    for (y = 0; y < rect.height; ++y) {
+    uint32_t* ptr = dst;
+    for (y = 0; y < rect.height; ++y, ptr += sub_image.argb_stride) {
       if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
-      Remap(gif, tmp, rect.width, transparent_index,
-            dst + y * sub_image.argb_stride);
+      Remap(gif, tmp, rect.width, transparent_index, ptr);
     }
   }
   ok = 1;
@@ -216,13 +224,11 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
 
 static void ClearRectangle(WebPPicture* const picture,
                            int left, int top, int width, int height) {
-  int j;
-  for (j = top; j < top + height; ++j) {
-    uint32_t* const dst = picture->argb + j * picture->argb_stride;
-    int i;
-    for (i = left; i < left + width; ++i) {
-      dst[i] = GIF_TRANSPARENT_COLOR;
-    }
+  int i, j;
+  const size_t stride = picture->argb_stride;
+  uint32_t* dst = picture->argb + top * stride + left;
+  for (j = 0; j < height; ++j, dst += stride) {
+    for (i = 0; i < width; ++i) dst[i] = GIF_TRANSPARENT_COLOR;
   }
 }
 
@@ -246,29 +252,31 @@ void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
   if (dispose == GIF_DISPOSE_BACKGROUND) {
     GIFClearPic(curr_canvas, rect);
   } else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
-    const int src_stride = prev_canvas->argb_stride;
-    const uint32_t* const src =
-        prev_canvas->argb + rect->x_offset + rect->y_offset * src_stride;
-    const int dst_stride = curr_canvas->argb_stride;
-    uint32_t* const dst =
-        curr_canvas->argb + rect->x_offset + rect->y_offset * dst_stride;
+    const size_t src_stride = prev_canvas->argb_stride;
+    const uint32_t* const src = prev_canvas->argb + rect->x_offset
+                              + rect->y_offset * src_stride;
+    const size_t dst_stride = curr_canvas->argb_stride;
+    uint32_t* const dst = curr_canvas->argb + rect->x_offset
+                        + rect->y_offset * dst_stride;
     assert(prev_canvas != NULL);
-    WebPCopyPlane((uint8_t*)src, 4 * src_stride, (uint8_t*)dst, 4 * dst_stride,
+    WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
+                  (uint8_t*)dst, (int)(4 * dst_stride),
                   4 * rect->width, rect->height);
   }
 }
 
 void GIFBlendFrames(const WebPPicture* const src,
                     const GIFFrameRect* const rect, WebPPicture* const dst) {
-  int j;
+  int i, j;
+  const size_t src_stride = src->argb_stride;
+  const size_t dst_stride = dst->argb_stride;
   assert(src->width == dst->width && src->height == dst->height);
   for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
-    int i;
     for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
-      const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
+      const uint32_t src_pixel = src->argb[j * src_stride + i];
       const int src_alpha = src_pixel >> 24;
       if (src_alpha != 0) {
-        dst->argb[j * dst->argb_stride + i] = src_pixel;
+        dst->argb[j * dst_stride + i] = src_pixel;
       }
     }
   }
-- 
2.10.1