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