s@failiure@failure@
[privoxy.git] / deanimate.c
1 const char deanimate_rcs[] = "$Id: deanimate.c,v 1.15 2007/01/03 14:39:19 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/deanimate.c,v $
5  *
6  * Purpose     :  Declares functions to manipulate binary images on the
7  *                fly.  High-level functions include:
8  *                  - Deanimation of GIF images
9  *                  - Fixup of malformed comment block in JPEG headers
10  *                
11  *                Functions declared include: gif_deanimate, buf_free,
12  *                buf_copy,  buf_getbyte, gif_skip_data_block,
13  *                gif_extract_image and jpeg_inspect
14  *
15  * Copyright   :  Written by and Copyright (C) 2001 - 2004, 2006 by the
16  *                SourceForge Privoxy team. http://www.privoxy.org/
17  *
18  *                Based on the GIF file format specification (see
19  *                http://tronche.com/computer-graphics/gif/gif89a.html)
20  *                and ideas from the Image::DeAnim Perl module by
21  *                Ken MacFarlane, <ksm+cpan@universal.dca.net>
22  *
23  *                This program is free software; you can redistribute it 
24  *                and/or modify it under the terms of the GNU General
25  *                Public License as published by the Free Software
26  *                Foundation; either version 2 of the License, or (at
27  *                your option) any later version.
28  *
29  *                This program is distributed in the hope that it will
30  *                be useful, but WITHOUT ANY WARRANTY; without even the
31  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
32  *                PARTICULAR PURPOSE.  See the GNU General Public
33  *                License for more details.
34  *
35  *                The GNU General Public License should be included with
36  *                this file.  If not, you can view it at
37  *                http://www.gnu.org/copyleft/gpl.html
38  *                or write to the Free Software Foundation, Inc., 59
39  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
40  *
41  * Revisions   :
42  *    $Log: deanimate.c,v $
43  *    Revision 1.15  2007/01/03 14:39:19  fabiankeil
44  *    Fix a gcc43 warning and mark the binbuffer
45  *    as immutable for buf_getbyte().
46  *
47  *    Revision 1.14  2006/07/18 14:48:45  david__schmidt
48  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
49  *    with what was really the latest development (the v_3_0_branch branch)
50  *
51  *    Revision 1.12.2.1  2004/10/03 12:53:32  david__schmidt
52  *    Add the ability to check jpeg images for invalid
53  *    lengths of comment blocks.  Defensive strategy
54  *    against the exploit:
55  *       Microsoft Security Bulletin MS04-028
56  *       Buffer Overrun in JPEG Processing (GDI+) Could
57  *       Allow Code Execution (833987)
58  *    Enabled with +inspect-jpegs in actions files.
59  *
60  *    Revision 1.12  2002/05/12 21:36:29  jongfoster
61  *    Correcting function comments
62  *
63  *    Revision 1.11  2002/03/26 22:29:54  swa
64  *    we have a new homepage!
65  *
66  *    Revision 1.10  2002/03/24 13:25:43  swa
67  *    name change related issues
68  *
69  *    Revision 1.9  2002/03/13 00:27:04  jongfoster
70  *    Killing warnings
71  *
72  *    Revision 1.8  2002/03/09 19:42:47  jongfoster
73  *    Fixing more warnings
74  *
75  *    Revision 1.7  2002/03/08 17:46:04  jongfoster
76  *    Fixing int/size_t warnings
77  *
78  *    Revision 1.6  2002/03/07 03:46:17  oes
79  *    Fixed compiler warnings
80  *
81  *    Revision 1.5  2001/09/10 10:16:06  oes
82  *    Silenced compiler warnings
83  *
84  *    Revision 1.4  2001/07/18 12:28:49  oes
85  *    - Added feature for extracting the first frame
86  *      to gif_deanimate
87  *    - Separated image buffer extension into buf_extend
88  *    - Extended gif deanimation to GIF87a (untested!)
89  *    - Cosmetics
90  *
91  *    Revision 1.3  2001/07/15 13:57:50  jongfoster
92  *    Adding #includes string.h and miscutil.h
93  *
94  *    Revision 1.2  2001/07/13 13:46:20  oes
95  *    Introduced GIF deanimation feature
96  *
97  *
98  **********************************************************************/
99 \f
100
101 #include "config.h"
102
103 #include <string.h>
104 #include <fcntl.h>
105
106 #include "errlog.h"
107 #include "project.h"
108 #include "deanimate.h"
109 #include "miscutil.h"
110
111 const char deanimate_h_rcs[] = DEANIMATE_H_VERSION;
112
113 /*********************************************************************
114  * 
115  * Function    :  buf_free
116  *
117  * Description :  Safely frees a struct binbuffer
118  *
119  * Parameters  :
120  *          1  :  buf = Pointer to the binbuffer to be freed
121  *
122  * Returns     :  N/A
123  *
124  *********************************************************************/
125 void buf_free(struct binbuffer *buf)
126 {
127    if (buf == NULL) return;
128
129    if (buf->buffer != NULL)
130    {
131       free(buf->buffer);
132    }
133
134    free(buf);
135
136 }
137
138
139 /*********************************************************************
140  * 
141  * Function    :  buf_extend
142  *
143  * Description :  Ensure that a given binbuffer can hold a given amount
144  *                of bytes, by reallocating its buffer if necessary.
145  *                Allocate new mem in chunks of 1024 bytes, so we don't
146  *                have to realloc() too often.
147  *
148  * Parameters  :
149  *          1  :  buf = Pointer to the binbuffer
150  *          2  :  length = Desired minimum size
151  *                
152  *
153  * Returns     :  0 on success, 1 on failure.
154  *
155  *********************************************************************/
156 int buf_extend(struct binbuffer *buf, size_t length)
157 {
158    char *newbuf;
159
160    if (buf->offset + length > buf->size)
161    {
162       buf->size = ((buf->size + length + (size_t)1023) & ~(size_t)1023);
163       newbuf = (char *)realloc(buf->buffer, buf->size);
164
165       if (newbuf == NULL)
166       {
167          freez(buf->buffer);
168          return 1;
169       }
170       else
171       {
172          buf->buffer = newbuf;
173          return 0;
174       }
175    }
176    return 0;
177
178 }
179
180
181 /*********************************************************************
182  * 
183  * Function    :  buf_copy
184  *
185  * Description :  Safely copies a given amount of bytes from one
186  *                struct binbuffer to another, advancing the
187  *                offsets appropriately.
188  *
189  * Parameters  :
190  *          1  :  src = Pointer to the source binbuffer
191  *          2  :  dst = Pointer to the destination binbuffer
192  *          3  :  length = Number of bytes to be copied
193  *
194  * Returns     :  0 on success, 1 on failure.
195  *
196  *********************************************************************/
197 int buf_copy(struct binbuffer *src, struct binbuffer *dst, size_t length)
198 {
199
200    /*
201     * Sanity check: Can't copy more data than we have
202     */
203    if (src->offset + length > src->size) 
204    {
205       return 1;
206    }
207
208    /*
209     * Ensure that dst can hold the new data
210     */
211    if (buf_extend(dst, length)) 
212    {
213       return 1;
214    }
215
216    /*
217     * Now that it's safe, memcpy() the desired amount of
218     * data from src to dst and adjust the offsets
219     */
220    memcpy(dst->buffer + dst->offset, src->buffer + src->offset, length);
221    src->offset += length;
222    dst->offset += length;
223
224    return 0;
225
226 }
227
228
229 /*********************************************************************
230  * 
231  * Function    :  buf_getbyte
232  *
233  * Description :  Safely gets a byte from a given binbuffer at a
234  *                given offset
235  *
236  * Parameters  :
237  *          1  :  src = Pointer to the source binbuffer
238  *          2  :  offset = Offset to the desired byte
239  *
240  * Returns     :  The byte on success, or 0 on failure
241  *
242  *********************************************************************/
243 unsigned char buf_getbyte(const struct binbuffer *src, size_t offset)
244 {
245    if (src->offset + offset < src->size)
246    {
247       return (unsigned char)*(src->buffer + src->offset + offset);
248    }
249    else
250    {
251       return '\0';
252    }
253
254 }
255
256
257 /*********************************************************************
258  * 
259  * Function    :  gif_skip_data_block
260  *
261  * Description :  Safely advances the offset of a given struct binbuffer
262  *                that contains a GIF image and whose offset is
263  *                positioned at the start of a data block, behind
264  *                that block.
265  *
266  * Parameters  :
267  *          1  :  buf = Pointer to the binbuffer
268  *
269  * Returns     :  0 on success, or 1 on failure
270  *
271  *********************************************************************/
272 int gif_skip_data_block(struct binbuffer *buf)
273 {
274    unsigned char c;
275
276    /* 
277     * Data blocks are sequences of chunks, which are headed
278     * by a one-byte length field, with the last chunk having
279     * zero length.
280     */
281    while((c = buf_getbyte(buf, 0)) != '\0')
282    {
283       buf->offset += (size_t)c + 1;
284       if (buf->offset >= buf->size - 1)
285       {
286          return 1;
287       }
288    }
289    buf->offset++;
290
291    return 0;
292
293 }
294
295
296 /*********************************************************************
297  * 
298  * Function    :  gif_extract_image
299  *
300  * Description :  Safely extracts an image data block from a given
301  *                struct binbuffer that contains a GIF image and whose
302  *                offset is positioned at the start of a data block 
303  *                into a given destination binbuffer.
304  *
305  * Parameters  :
306  *          1  :  src = Pointer to the source binbuffer
307  *          2  :  dst = Pointer to the destination binbuffer
308  *
309  * Returns     :  0 on success, or 1 on failure
310  *
311  *********************************************************************/
312 int gif_extract_image(struct binbuffer *src, struct binbuffer *dst)
313 {
314    unsigned char c;
315
316    /*
317     * Remember the colormap flag and copy the image head
318     */
319    c = buf_getbyte(src, 9);
320    if (buf_copy(src, dst, 10))
321    {
322       return 1;
323    }
324
325    /*
326     * If the image has a local colormap, copy it.
327     */
328    if (c & 0x80)
329    {
330       if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
331       {
332          return 1;
333       }           
334    }
335    if (buf_copy(src, dst, 1)) return 1;
336
337    /*
338     * Copy the image chunk by chunk.
339     */
340    while((c = buf_getbyte(src, 0)) != '\0')
341    {
342       if (buf_copy(src, dst, 1 + (size_t) c)) return 1;
343    }
344    if (buf_copy(src, dst, 1)) return 1;
345
346    /*
347     * Trim and rewind the dst buffer
348     */
349    if (NULL == (dst->buffer = (char *)realloc(dst->buffer, dst->offset))) return 1;
350    dst->size = dst->offset;
351    dst->offset = 0;
352
353    return(0);
354
355 }
356
357 /*********************************************************************
358  * 
359  * Function    :  gif_deanimate
360  *
361  * Description :  Deanimate a given GIF image, i.e. given a GIF with
362  *                an (optional) image block and an arbitrary number
363  *                of image extension blocks, produce an output GIF with
364  *                only one image block that contains the last image
365  *                (extenstion) block of the original.
366  *                Also strip Comments, Application extenstions, etc.
367  *
368  * Parameters  :
369  *          1  :  src = Pointer to the source binbuffer
370  *          2  :  dst = Pointer to the destination binbuffer
371  *          3  :  get_first_image = Flag: If set, get the first image
372  *                                        If unset (default), get the last
373  *
374  * Returns     :  0 on success, or 1 on failure
375  *
376  *********************************************************************/
377 int gif_deanimate(struct binbuffer *src, struct binbuffer *dst, int get_first_image)
378 {
379    unsigned char c;
380    struct binbuffer *image;
381
382    if (NULL == src || NULL == dst)
383    {
384       return 1;
385    }
386
387    c = buf_getbyte(src, 10);
388
389    /*
390     * Check & copy GIF header 
391     */
392    if (strncmp(src->buffer, "GIF89a", 6) && strncmp(src->buffer, "GIF87a", 6)) 
393    {
394       return 1;
395    }
396    else
397    {
398       if (buf_copy(src, dst, 13))
399       {
400          return 1;
401       }
402    }
403
404    /*
405     * Look for global colormap and  copy if found.
406     */
407    if(c & 0x80)
408    {
409       if (buf_copy(src, dst, (size_t) 3 * (1 << ((c & 0x07) + 1))))
410       {
411          return 1;
412       }
413    }
414
415    /*
416     * Reserve a buffer for the current image block
417     */
418    if (NULL == (image = (struct binbuffer *)zalloc(sizeof(*image))))
419    {
420       return 1;
421    }
422
423    /*
424     * Parse the GIF block by block and copy the relevant
425     * parts to dst
426     */
427    while(src->offset < src->size)
428    {
429       switch(buf_getbyte(src, 0))
430       {
431          /*
432           *  End-of-GIF Marker: Append current image and return
433           */
434       case 0x3b:
435          goto write;
436
437          /* 
438           * Image block: Extract to current image buffer.
439           */
440       case 0x2c:
441          image->offset = 0;
442          if (gif_extract_image(src, image)) goto failed;
443          if (get_first_image) goto write;
444          continue;
445
446          /*
447           * Extension block: Look at next byte and decide
448           */
449       case 0x21:
450          switch (buf_getbyte(src, 1))
451          {
452             /*
453              * Image extension: Copy extension  header and image
454              *                  to the current image buffer
455              */
456          case 0xf9:
457             image->offset = 0;
458             if (buf_copy(src, image, 8) || buf_getbyte(src, 0) != 0x2c) goto failed;
459             if (gif_extract_image(src, image)) goto failed;
460             if (get_first_image) goto write;
461             continue;
462
463             /*
464              * Application extension: Skip
465              */
466          case 0xff:
467             if ((src->offset += 14) >= src->size || gif_skip_data_block(src)) goto failed;
468             continue;
469
470             /*
471              * Comment extension: Skip
472              */
473          case 0xfe:
474             if ((src->offset += 2) >= src->size || gif_skip_data_block(src)) goto failed;
475             continue;
476
477             /*
478              * Plain text extension: Skip
479              */
480          case 0x01:
481             if ((src->offset += 15) >= src->size || gif_skip_data_block(src)) goto failed;
482             continue;
483
484             /*
485              * Ooops, what type of extension is that?
486              */
487          default:
488             goto failed;
489
490          }
491
492          /*
493           * Ooops, what type of block is that?
494           */
495       default:
496          goto failed;
497          
498       }
499    } /* -END- while src */
500
501    /*
502     * Either we got here by goto, or because the GIF is
503     * bogus and EOF was reached before an end-of-gif marker 
504     * was found.
505     */
506
507 failed:
508    buf_free(image);
509    return 1;
510
511    /*
512     * Append the current image to dst and return
513     */
514
515 write:
516    if (buf_copy(image, dst, image->size)) goto failed;
517    if (buf_extend(dst, 1)) goto failed;
518    *(dst->buffer + dst->offset++) = 0x3b;
519    buf_free(image);
520    return 0;
521
522 }
523
524
525 /*********************************************************************
526  * 
527  * Function    :  jpeg_inspect
528  *
529  * Description :  Checks a jpeg image for an invalid length in a 
530  *                comment block (0xFFFE0000 or 0xFFFE0001) and
531  *                changes it to 0xFFFE0002.  Defensive strategy 
532  *                against the exploit:
533  *                  Microsoft Security Bulletin MS04-028
534  *                  Buffer Overrun in JPEG Processing (GDI+) Could
535  *                  Allow Code Execution (833987)
536  *
537  * Parameters  :
538  *          1  :  src = Pointer to the image binbuffer
539  *
540  * Returns     :  0 on success, or 1 on failure
541  *
542  *********************************************************************/
543 int jpeg_inspect(struct binbuffer *src, struct binbuffer *dst)
544 {
545    long i;
546    /*
547     * We process the image using a simple finite state machine, 
548     * searching for byte patterns.
549     */
550    enum { J_INIT, /* The initial state */
551           J_FF,   /* Found byte 0xFF */
552           J_FE,   /* Found bytes 0xFF 0xFE */
553           J_00,   /* Found bytes 0xFF 0xFE 0x00 */
554           J_DA    /*
555                    * Found bytes 0xFF 0xDA; short-circuit to done-ness
556                    * since this signals the beginning end of headers.
557                    */
558         };
559    short state = J_INIT;
560    unsigned char c;
561
562    if (NULL == src || NULL == dst)
563    {
564       return 1;
565    }
566
567    if (buf_copy(src, dst, src->size))
568    {
569       return 1;
570    }
571
572    /* Need to search the jpg for patterns:
573     * 0xFF 0xFE 0x00 0x00
574     * or 
575     * 0xFF 0xFE 0x00 0x01
576     * from beginning until:
577     * 0xFF 0xDA
578     * (or the end of the buffer)
579     * If found, change the pattern to 0xFF 0xFE 0x00 0x02
580     */
581
582    for (i = 0; i < dst->size; i++)
583    {
584       c = dst->buffer[i];
585       switch (state)
586       {
587          case J_INIT:
588             if (c == 0xFF)
589                state = J_FF;
590             break;
591          case J_FF:
592             if (c == 0xDA)
593                state = J_DA; /* End of headers - we're done with this image. */
594             else if (c == 0xFE)
595                state = J_FE;
596             else
597                state = J_INIT;
598             break;
599          case J_FE:
600             if (c == 0x00)
601                state = J_00;
602             else
603                state = J_INIT;
604             break;
605          case J_00:
606             if ((c == 0x00) || (c == 0x01))
607             {
608                dst->buffer[i] = 2; /* Reset comment block size to 2. */
609                log_error(LOG_LEVEL_INFO, "JPEG comment exploit removed.");
610                /* TODO:
611                 * I'm unsure if we can have more than one comment block.  Just in case,
612                 * we'll scan the rest of the header for more by going back to J_INIT
613                 * state.  If there is no possibility of >1 comment block, we could 
614                 * short-circuit to done-ness here.
615                 */
616                state = J_INIT;
617             }
618             else
619                state = J_INIT;
620             break;
621          default:
622             break;
623       }
624       if (state == J_DA)
625          break;
626    }
627
628    return 0;
629 }
630
631
632 /*
633   Local Variables:
634   tab-width: 3
635   end:
636 */