~ubuntu-branches/ubuntu/maverick/libpng/maverick-updates

« back to all changes in this revision

Viewing changes to debian/patches/02-CVE-2010-0205.patch

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2010-03-03 16:44:47 UTC
  • mfrom: (1.1.12 upstream) (15.2.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100303164447-2w5p75b0cfsrft5t
Tags: 1.2.43-1
* New upstream release 
* Fix CVE-2010-0205 and Cert VU#576029
  http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0205
  https://www.kb.cert.org/vuls/id/576029
  Do not stall and consume large quantities of memory while processing
  certain Portable Network Graphics (PNG) files
  Closes: 572308

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Description: fix denial of service via decompression bomb
2
 
Origin: backported from 1.2.43 
3
 
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libpng/+bug/533140
4
 
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572308
5
 
 
6
 
Index: libpng-1.2.42/pngrutil.c
7
 
===================================================================
8
 
--- libpng-1.2.42.orig/pngrutil.c       2010-01-03 00:04:19.000000000 -0500
9
 
+++ libpng-1.2.42/pngrutil.c    2010-03-11 14:52:59.000000000 -0500
10
 
@@ -217,180 +217,193 @@
11
 
 
12
 
 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
13
 
     defined(PNG_READ_iCCP_SUPPORTED)
14
 
-/*
15
 
- * Decompress trailing data in a chunk.  The assumption is that chunkdata
16
 
- * points at an allocated area holding the contents of a chunk with a
17
 
- * trailing compressed part.  What we get back is an allocated area
18
 
- * holding the original prefix part and an uncompressed version of the
19
 
- * trailing part (the malloc area passed in is freed).
20
 
- */
21
 
-void /* PRIVATE */
22
 
-png_decompress_chunk(png_structp png_ptr, int comp_type,
23
 
-                              png_size_t chunklength,
24
 
-                              png_size_t prefix_size, png_size_t *newlength)
25
 
+static png_size_t
26
 
+png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
27
 
+       png_bytep output, png_size_t output_size)
28
 
 {
29
 
-   static PNG_CONST char msg[] = "Error decoding compressed chunk";
30
 
-   png_charp text;
31
 
-   png_size_t text_size;
32
 
+   png_size_t count = 0;
33
 
 
34
 
-   if (comp_type == PNG_COMPRESSION_TYPE_BASE)
35
 
+   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
36
 
+   png_ptr->zstream.avail_in = size;
37
 
+
38
 
+   while (1)
39
 
    {
40
 
-      int ret = Z_OK;
41
 
-      png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
42
 
-      png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
43
 
+      int ret, avail;
44
 
+
45
 
+      /* Reset the output buffer each time round - we empty it
46
 
+       * after every inflate call.
47
 
+       */
48
 
       png_ptr->zstream.next_out = png_ptr->zbuf;
49
 
-      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
50
 
+      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
51
 
 
52
 
-      text_size = 0;
53
 
-      text = NULL;
54
 
+      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
55
 
+      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
56
 
 
57
 
-      while (png_ptr->zstream.avail_in)
58
 
-      {
59
 
-         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
60
 
-         if (ret != Z_OK && ret != Z_STREAM_END)
61
 
-         {
62
 
-            if (png_ptr->zstream.msg != NULL)
63
 
-               png_warning(png_ptr, png_ptr->zstream.msg);
64
 
-            else
65
 
-               png_warning(png_ptr, msg);
66
 
-            inflateReset(&png_ptr->zstream);
67
 
-            png_ptr->zstream.avail_in = 0;
68
 
-
69
 
-            if (text ==  NULL)
70
 
-            {
71
 
-               text_size = prefix_size + png_sizeof(msg) + 1;
72
 
-               text = (png_charp)png_malloc_warn(png_ptr, text_size);
73
 
-               if (text ==  NULL)
74
 
-                 {
75
 
-                    png_free(png_ptr, png_ptr->chunkdata);
76
 
-                    png_ptr->chunkdata = NULL;
77
 
-                    png_error(png_ptr, "Not enough memory to decompress chunk");
78
 
-                 }
79
 
-               png_memcpy(text, png_ptr->chunkdata, prefix_size);
80
 
-            }
81
 
-
82
 
-            text[text_size - 1] = 0x00;
83
 
-
84
 
-            /* Copy what we can of the error message into the text chunk */
85
 
-            text_size = (png_size_t)(chunklength -
86
 
-              (text - png_ptr->chunkdata) - 1);
87
 
-            if (text_size > png_sizeof(msg))
88
 
-               text_size = png_sizeof(msg);
89
 
-            png_memcpy(text + prefix_size, msg, text_size);
90
 
-            break;
91
 
-         }
92
 
-         if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
93
 
-         {
94
 
-            if (text == NULL)
95
 
-            {
96
 
-               text_size = prefix_size +
97
 
-                   png_ptr->zbuf_size - png_ptr->zstream.avail_out;
98
 
-               text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
99
 
-               if (text ==  NULL)
100
 
-               {
101
 
-                  png_free(png_ptr, png_ptr->chunkdata);
102
 
-                  png_ptr->chunkdata = NULL;
103
 
-                  png_error(png_ptr,
104
 
-                    "Not enough memory to decompress chunk.");
105
 
-               }
106
 
-               png_memcpy(text + prefix_size, png_ptr->zbuf,
107
 
-                    text_size - prefix_size);
108
 
-               png_memcpy(text, png_ptr->chunkdata, prefix_size);
109
 
-               *(text + text_size) = 0x00;
110
 
-            }
111
 
-            else
112
 
-            {
113
 
-               png_charp tmp;
114
 
-
115
 
-               tmp = text;
116
 
-                  text = (png_charp)png_malloc_warn(png_ptr,
117
 
-                     (png_uint_32)(text_size +
118
 
-                      png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
119
 
-               if (text == NULL)
120
 
-               {
121
 
-                  png_free(png_ptr, tmp);
122
 
-                  png_free(png_ptr, png_ptr->chunkdata);
123
 
-                  png_ptr->chunkdata = NULL;
124
 
-                  png_error(png_ptr,
125
 
-                    "Not enough memory to decompress chunk..");
126
 
-               }
127
 
-               png_memcpy(text, tmp, text_size);
128
 
-               png_free(png_ptr, tmp);
129
 
-               png_memcpy(text + text_size, png_ptr->zbuf,
130
 
-                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
131
 
-               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
132
 
-               *(text + text_size) = 0x00;
133
 
-            }
134
 
-            if (ret == Z_STREAM_END)
135
 
-               break;
136
 
-            else
137
 
-            {
138
 
-               png_ptr->zstream.next_out = png_ptr->zbuf;
139
 
-               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
140
 
-            }
141
 
-         }
142
 
-      }
143
 
-      if (ret != Z_STREAM_END)
144
 
-      {
145
 
-#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
146
 
-         char umsg[52];
147
 
+      /* First copy/count any new output - but only if we didn't
148
 
+       * get an error code.
149
 
+       */
150
 
+      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
151
 
+      {
152
 
+         if (output != 0 && output_size > count)
153
 
+        {
154
 
+           int copy = output_size - count;
155
 
+           if (avail < copy) copy = avail;
156
 
+           png_memcpy(output + count, png_ptr->zbuf, copy);
157
 
+        }
158
 
+         count += avail;
159
 
+      }
160
 
+
161
 
+      if (ret == Z_OK)
162
 
+         continue;
163
 
+
164
 
+      /* Termination conditions - always reset the zstream, it
165
 
+       * must be left in inflateInit state.
166
 
+       */
167
 
+      png_ptr->zstream.avail_in = 0;
168
 
+      inflateReset(&png_ptr->zstream);
169
 
 
170
 
-         if (ret == Z_BUF_ERROR)
171
 
-            png_snprintf(umsg, 52,
172
 
-                "Buffer error in compressed datastream in %s chunk",
173
 
-                png_ptr->chunk_name);
174
 
-
175
 
-         else if (ret == Z_DATA_ERROR)
176
 
-            png_snprintf(umsg, 52,
177
 
-                "Data error in compressed datastream in %s chunk",
178
 
-                png_ptr->chunk_name);
179
 
+      if (ret == Z_STREAM_END)
180
 
+         return count; /* NOTE: may be zero. */
181
 
 
182
 
-         else
183
 
-            png_snprintf(umsg, 52,
184
 
-                "Incomplete compressed datastream in %s chunk",
185
 
-                png_ptr->chunk_name);
186
 
+      /* Now handle the error codes - the API always returns 0
187
 
+       * and the error message is dumped into the uncompressed
188
 
+       * buffer if available.
189
 
+       */
190
 
+      {
191
 
+         char *msg, umsg[52];
192
 
+        if (png_ptr->zstream.msg != 0)
193
 
+           msg = png_ptr->zstream.msg;
194
 
+        else
195
 
+        {
196
 
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
197
 
+           switch (ret)
198
 
+           {
199
 
+        case Z_BUF_ERROR:
200
 
+           msg = "Buffer error in compressed datastream in %s chunk";
201
 
+           break;
202
 
+        case Z_DATA_ERROR:
203
 
+           msg = "Data error in compressed datastream in %s chunk";
204
 
+           break;
205
 
+        default:
206
 
+           msg = "Incomplete compressed datastream in %s chunk";
207
 
+           break;
208
 
+           }
209
 
 
210
 
-         png_warning(png_ptr, umsg);
211
 
+           png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
212
 
+           msg = umsg;
213
 
 #else
214
 
-         png_warning(png_ptr,
215
 
-            "Incomplete compressed datastream in chunk other than IDAT");
216
 
+           msg = "Damaged compressed datastream in chunk other than IDAT";
217
 
 #endif
218
 
-         text_size = prefix_size;
219
 
-         if (text ==  NULL)
220
 
-         {
221
 
-            text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
222
 
-            if (text == NULL)
223
 
-              {
224
 
-                png_free(png_ptr, png_ptr->chunkdata);
225
 
-                png_ptr->chunkdata = NULL;
226
 
-                png_error(png_ptr, "Not enough memory for text.");
227
 
-              }
228
 
-            png_memcpy(text, png_ptr->chunkdata, prefix_size);
229
 
-         }
230
 
-         *(text + text_size) = 0x00;
231
 
+        }
232
 
+
233
 
+         png_warning(png_ptr, msg);
234
 
       }
235
 
 
236
 
-      inflateReset(&png_ptr->zstream);
237
 
-      png_ptr->zstream.avail_in = 0;
238
 
+      /* 0 means an error - notice that this code simple ignores
239
 
+       * zero length compressed chunks as a result.
240
 
+       */
241
 
+      return 0;
242
 
+   }
243
 
+}
244
 
 
245
 
-      png_free(png_ptr, png_ptr->chunkdata);
246
 
-      png_ptr->chunkdata = text;
247
 
-      *newlength=text_size;
248
 
+/*
249
 
+ * Decompress trailing data in a chunk.  The assumption is that chunkdata
250
 
+ * points at an allocated area holding the contents of a chunk with a
251
 
+ * trailing compressed part.  What we get back is an allocated area
252
 
+ * holding the original prefix part and an uncompressed version of the
253
 
+ * trailing part (the malloc area passed in is freed).
254
 
+ */
255
 
+void /* PRIVATE */
256
 
+png_decompress_chunk(png_structp png_ptr, int comp_type,
257
 
+    png_size_t chunklength,
258
 
+    png_size_t prefix_size, png_size_t *newlength)
259
 
+{
260
 
+   /* The caller should guarantee this */
261
 
+   if (prefix_size > chunklength)
262
 
+   {
263
 
+      /* The recovery is to delete the chunk. */
264
 
+      png_warning(png_ptr, "invalid chunklength");
265
 
+      prefix_size = 0; /* To delete everything */
266
 
+   }
267
 
+
268
 
+   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
269
 
+   {
270
 
+      png_size_t expanded_size = png_inflate(png_ptr,
271
 
+               (png_bytep)(png_ptr->chunkdata + prefix_size),
272
 
+                chunklength - prefix_size,
273
 
+               0/*output*/, 0/*output size*/);
274
 
+
275
 
+      /* If the size is zero either there was an error and a message
276
 
+       * has already been output (warning) or the size really is zero
277
 
+       * and we have nothing to do - the code will exit through the
278
 
+       * error case below.
279
 
+       */
280
 
+      if (expanded_size > 0)
281
 
+      {
282
 
+         /* Success (maybe) - really uncompress the chunk. */
283
 
+        png_size_t new_size = 0;
284
 
+        png_charp text = png_malloc_warn(png_ptr,
285
 
+                       prefix_size + expanded_size + 1);
286
 
+
287
 
+         if (text != NULL)
288
 
+         {
289
 
+           png_memcpy(text, png_ptr->chunkdata, prefix_size);
290
 
+           new_size = png_inflate(png_ptr,
291
 
+                (png_bytep)(png_ptr->chunkdata + prefix_size),
292
 
+               chunklength - prefix_size,
293
 
+                (png_bytep)(text + prefix_size), expanded_size);
294
 
+           text[prefix_size + expanded_size] = 0; /* just in case */
295
 
+
296
 
+           if (new_size == expanded_size)
297
 
+           {
298
 
+              png_free(png_ptr, png_ptr->chunkdata);
299
 
+              png_ptr->chunkdata = text;
300
 
+              *newlength = prefix_size + expanded_size;
301
 
+              return; /* The success return! */
302
 
+           }
303
 
+      
304
 
+           png_warning(png_ptr, "png_inflate logic error");
305
 
+           png_free(png_ptr, text);
306
 
+        }
307
 
+        else
308
 
+          png_warning(png_ptr, "Not enough memory to decompress chunk.");
309
 
+      }
310
 
    }
311
 
+
312
 
    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
313
 
    {
314
 
-#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
315
 
       char umsg[50];
316
 
 
317
 
-      png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
318
 
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
319
 
+      png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d", comp_type);
320
 
       png_warning(png_ptr, umsg);
321
 
 #else
322
 
       png_warning(png_ptr, "Unknown zTXt compression type");
323
 
 #endif
324
 
 
325
 
-      *(png_ptr->chunkdata + prefix_size) = 0x00;
326
 
-      *newlength = prefix_size;
327
 
+      /* The recovery is to simply drop the data. */
328
 
    }
329
 
+
330
 
+   /* Generic error return - leave the prefix, delete the compressed
331
 
+    * data, reallocate the chunkdata to remove the potentially large
332
 
+    * amount of compressed data.
333
 
+    */
334
 
+   {
335
 
+      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
336
 
+      if (text != NULL)
337
 
+      {
338
 
+        if (prefix_size > 0)
339
 
+            png_memcpy(text, png_ptr->chunkdata, prefix_size);
340
 
+        png_free(png_ptr, png_ptr->chunkdata);
341
 
+        png_ptr->chunkdata = text;
342
 
+
343
 
+        /* This is an extra zero in the 'uncompressed' part. */
344
 
+        *(png_ptr->chunkdata + prefix_size) = 0x00;
345
 
+      }
346
 
+      /* Ignore a malloc error here - it is safe. */
347
 
+   }
348
 
+
349
 
+   *newlength = prefix_size;
350
 
 }
351
 
 #endif
352