1 /* gifread.c - Functions to read GIFs.
2    Copyright (C) 1997-2019 Eddie Kohler, ekohler@gmail.com
3    This file is part of the LCDF GIF library.
4 
5    The LCDF GIF library is free software. It is distributed under the GNU
6    General Public License, version 2; you can copy, distribute, or alter it at
7    will, as long as this notice is kept intact and this source code is made
8    available. There is no warranty, express or implied. */
9 
10 #if HAVE_CONFIG_H
11 # include <config.h>
12 #elif !defined(__cplusplus)
13 /* Assume we don't have inline by default */
14 # define inline
15 #endif
16 #include <lcdfgif/gif.h>
17 #include <stdarg.h>
18 #include <assert.h>
19 #include <string.h>
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 typedef struct {
25 
26   Gif_Stream *stream;
27 
28   Gif_Code *prefix;
29   uint8_t *suffix;
30   uint16_t *length;
31 
32   uint16_t width;
33   uint16_t height;
34 
35   uint8_t *image;
36   uint8_t *maximage;
37 
38   unsigned decodepos;
39 
40   Gif_Image* gfi;
41   Gif_ReadErrorHandler handler;
42   int errors[2];
43 
44 } Gif_Context;
45 
46 
47 typedef struct Gif_Reader {
48   FILE *f;
49   const uint8_t *v;
50   uint32_t pos;
51   uint32_t length;
52   int is_record;
53   int is_eoi;
54   uint8_t (*byte_getter)(struct Gif_Reader *);
55   uint32_t (*block_getter)(uint8_t*, uint32_t, struct Gif_Reader*);
56   int (*eofer)(struct Gif_Reader *);
57 } Gif_Reader;
58 
59 static Gif_ReadErrorHandler default_error_handler = 0;
60 
61 
62 #define gifgetc(grr)    ((char)(*grr->byte_getter)(grr))
63 #define gifgetbyte(grr) ((*grr->byte_getter)(grr))
64 #define gifgetblock(ptr, size, grr) ((*grr->block_getter)(ptr, size, grr))
65 #define gifeof(grr)     ((*grr->eofer)(grr))
66 
67 static inline uint16_t
gifgetunsigned(Gif_Reader * grr)68 gifgetunsigned(Gif_Reader *grr)
69 {
70   uint8_t one = gifgetbyte(grr);
71   uint8_t two = gifgetbyte(grr);
72   return one | (two << 8);
73 }
74 
75 
76 static uint8_t
file_byte_getter(Gif_Reader * grr)77 file_byte_getter(Gif_Reader *grr)
78 {
79     int i = getc(grr->f);
80     if (i != EOF) {
81         ++grr->pos;
82         return i;
83     } else
84         return 0;
85 }
86 
87 static uint32_t
file_block_getter(uint8_t * p,uint32_t s,Gif_Reader * grr)88 file_block_getter(uint8_t *p, uint32_t s, Gif_Reader *grr)
89 {
90     size_t nread = fread(p, 1, s, grr->f);
91     if (nread < s)
92         memset(p + nread, 0, s - nread);
93     grr->pos += nread;
94     return nread;
95 }
96 
97 static int
file_eofer(Gif_Reader * grr)98 file_eofer(Gif_Reader *grr)
99 {
100   int c = getc(grr->f);
101   if (c == EOF)
102     return 1;
103   else {
104     ungetc(c, grr->f);
105     return 0;
106   }
107 }
108 
109 
110 static uint8_t
record_byte_getter(Gif_Reader * grr)111 record_byte_getter(Gif_Reader *grr)
112 {
113     if (grr->pos < grr->length)
114         return grr->v[grr->pos++];
115     else
116         return 0;
117 }
118 
119 static uint32_t
record_block_getter(uint8_t * p,uint32_t s,Gif_Reader * grr)120 record_block_getter(uint8_t *p, uint32_t s, Gif_Reader *grr)
121 {
122     uint32_t ncopy = (grr->pos + s <= grr->length ? s : grr->length - grr->pos);
123     memcpy(p, &grr->v[grr->pos], ncopy);
124     grr->pos += ncopy;
125     if (ncopy < s)
126         memset(p + ncopy, 0, s - ncopy);
127     return ncopy;
128 }
129 
130 static int
record_eofer(Gif_Reader * grr)131 record_eofer(Gif_Reader *grr)
132 {
133     return grr->pos == grr->length;
134 }
135 
136 
137 static void
make_data_reader(Gif_Reader * grr,const uint8_t * data,uint32_t length)138 make_data_reader(Gif_Reader *grr, const uint8_t *data, uint32_t length)
139 {
140   grr->v = data;
141   grr->pos = 0;
142   grr->length = length;
143   grr->is_record = 1;
144   grr->byte_getter = record_byte_getter;
145   grr->block_getter = record_block_getter;
146   grr->eofer = record_eofer;
147 }
148 
149 
150 static void
gif_read_error(Gif_Context * gfc,int is_error,const char * text)151 gif_read_error(Gif_Context *gfc, int is_error, const char *text)
152 {
153     Gif_ReadErrorHandler handler = gfc->handler ? gfc->handler : default_error_handler;
154     if (is_error >= 0)
155         gfc->errors[is_error > 0] += 1;
156     if (handler)
157         handler(gfc->stream, gfc->gfi, is_error, text);
158 }
159 
160 
161 static uint8_t
one_code(Gif_Context * gfc,Gif_Code code)162 one_code(Gif_Context *gfc, Gif_Code code)
163 {
164   uint8_t *suffixes = gfc->suffix;
165   Gif_Code *prefixes = gfc->prefix;
166   uint8_t *ptr;
167   int lastsuffix = 0;
168   int codelength = gfc->length[code];
169 
170   gfc->decodepos += codelength;
171   ptr = gfc->image + gfc->decodepos;
172   while (codelength > 0) {
173       lastsuffix = suffixes[code];
174       code = prefixes[code];
175       --ptr;
176       if (ptr < gfc->maximage)
177           *ptr = lastsuffix;
178       --codelength;
179   }
180 
181   /* return the first pixel in the code, which, since we walked backwards
182      through the code, was the last suffix we processed. */
183   return lastsuffix;
184 }
185 
186 static int
read_image_block(Gif_Reader * grr,uint8_t * buffer,int * bit_pos_store,int * bit_len_store,int bits_needed)187 read_image_block(Gif_Reader *grr, uint8_t *buffer, int *bit_pos_store,
188                  int *bit_len_store, int bits_needed)
189 {
190   int bit_position = *bit_pos_store;
191   int bit_length = *bit_len_store;
192   uint8_t block_len;
193 
194   while (bit_position + bits_needed > bit_length) {
195     /* Read in the next data block. */
196     if (bit_position >= 8) {
197       /* Need to shift down the upper, unused part of 'buffer' */
198       int i = bit_position / 8;
199       buffer[0] = buffer[i];
200       buffer[1] = buffer[i+1];
201       bit_position -= i * 8;
202       bit_length -= i * 8;
203     }
204     block_len = gifgetbyte(grr);
205     GIF_DEBUG(("\nimage_block(%d) ", block_len));
206     if (block_len == 0) return 0;
207     gifgetblock(buffer + bit_length / 8, block_len, grr);
208     bit_length += block_len * 8;
209   }
210 
211   *bit_pos_store = bit_position;
212   *bit_len_store = bit_length;
213   return 1;
214 }
215 
216 
217 static void
read_image_data(Gif_Context * gfc,Gif_Reader * grr)218 read_image_data(Gif_Context *gfc, Gif_Reader *grr)
219 {
220   /* we need a bit more than GIF_MAX_BLOCK in case a single code is split
221      across blocks */
222   uint8_t buffer[GIF_MAX_BLOCK + 5];
223   int i;
224   uint32_t accum;
225 
226   int bit_position;
227   int bit_length;
228 
229   Gif_Code code;
230   Gif_Code old_code;
231   Gif_Code clear_code;
232   Gif_Code eoi_code;
233   Gif_Code next_code;
234 #define CUR_BUMP_CODE (1 << bits_needed)
235 #define CUR_CODE_MASK ((1 << bits_needed) - 1)
236 
237   int min_code_size;
238   int bits_needed;
239 
240   gfc->decodepos = 0;
241 
242   min_code_size = gifgetbyte(grr);
243   GIF_DEBUG(("\n\nmin_code_size(%d) ", min_code_size));
244   if (min_code_size >= GIF_MAX_CODE_BITS) {
245     gif_read_error(gfc, 1, "image corrupted, min_code_size too big");
246     min_code_size = GIF_MAX_CODE_BITS - 1;
247   } else if (min_code_size < 2) {
248     gif_read_error(gfc, 1, "image corrupted, min_code_size too small");
249     min_code_size = 2;
250   }
251   clear_code = 1 << min_code_size;
252   for (code = 0; code < clear_code; code++) {
253     gfc->prefix[code] = 49428;
254     gfc->suffix[code] = (uint8_t)code;
255     gfc->length[code] = 1;
256   }
257   eoi_code = clear_code + 1;
258 
259   next_code = eoi_code;
260   bits_needed = min_code_size + 1;
261 
262   code = clear_code;
263 
264   bit_length = bit_position = 0;
265   /* Thus the 'Read in the next data block.' code below will be invoked on the
266      first time through: exactly right! */
267 
268   while (1) {
269 
270     old_code = code;
271 
272     /* GET A CODE INTO THE 'code' VARIABLE.
273      *
274      * 9.Dec.1998 - Rather than maintain a byte pointer and a bit offset into
275      * the current byte (and the processing associated with that), we maintain
276      * one number: the offset, in bits, from the beginning of 'buffer'. This
277      * much cleaner choice was inspired by Patrick J. Naughton
278      * <naughton@wind.sun.com>'s GIF-reading code, which does the same thing.
279      * His code distributed as part of XV in xvgif.c. */
280 
281     if (bit_position + bits_needed > bit_length)
282       /* Read in the next data block. */
283       if (!read_image_block(grr, buffer, &bit_position, &bit_length,
284                             bits_needed))
285         goto zero_length_block;
286 
287     i = bit_position / 8;
288     accum = buffer[i] + (buffer[i+1] << 8);
289     if (bits_needed >= 8)
290       accum |= (buffer[i+2]) << 16;
291     code = (Gif_Code)((accum >> (bit_position % 8)) & CUR_CODE_MASK);
292     bit_position += bits_needed;
293 
294     GIF_DEBUG(("%d ", code));
295 
296     /* CHECK FOR SPECIAL OR BAD CODES: clear_code, eoi_code, or a code that is
297      * too large. */
298     if (code == clear_code) {
299       GIF_DEBUG(("clear "));
300       bits_needed = min_code_size + 1;
301       next_code = eoi_code;
302       continue;
303 
304     } else if (code == eoi_code)
305       break;
306 
307     else if (code > next_code && next_code && next_code != clear_code) {
308       /* code > next_code: a (hopefully recoverable) error.
309 
310          Bug fix, 5/27: Do this even if old_code == clear_code, and set code
311          to 0 to prevent errors later. (If we didn't zero code, we'd later set
312          old_code = code; then we had old_code >= next_code; so the prefixes
313          array got all screwed up!)
314 
315          Bug fix, 4/12/2010: It is not an error if next_code == clear_code.
316          This happens at the end of a large GIF: see the next comment ("If no
317          meaningful next code should be defined...."). */
318       if (gfc->errors[1] < 20)
319           gif_read_error(gfc, 1, "image corrupted, code out of range");
320       else if (gfc->errors[1] == 20)
321           gif_read_error(gfc, 1, "(not reporting more errors)");
322       code = 0;
323     }
324 
325     /* PROCESS THE CURRENT CODE and define the next code. If no meaningful
326      * next code should be defined, then we have set next_code to either
327      * 'eoi_code' or 'clear_code' -- so we'll store useless prefix/suffix data
328      * in a useless place. */
329 
330     /* *First,* set up the prefix and length for the next code
331        (in case code == next_code). */
332     gfc->prefix[next_code] = old_code;
333     gfc->length[next_code] = gfc->length[old_code] + 1;
334 
335     /* Use one_code to process code. It's nice that it returns the first
336        pixel in code: that's what we need. */
337     gfc->suffix[next_code] = one_code(gfc, code);
338 
339     /* Special processing if code == next_code: we didn't know code's final
340        suffix when we called one_code, but we do now. */
341     /* 7.Mar.2014 -- Avoid error if image has zero width/height. */
342     if (code == next_code && gfc->image + gfc->decodepos <= gfc->maximage)
343       gfc->image[gfc->decodepos - 1] = gfc->suffix[next_code];
344 
345     /* Increment next_code except for the 'clear_code' special case (that's
346        when we're reading at the end of a GIF) */
347     if (next_code != clear_code) {
348       next_code++;
349       if (next_code == CUR_BUMP_CODE) {
350         if (bits_needed < GIF_MAX_CODE_BITS)
351           bits_needed++;
352         else
353           next_code = clear_code;
354       }
355     }
356 
357   }
358 
359   /* read blocks until zero-length reached. */
360   i = gifgetbyte(grr);
361   GIF_DEBUG(("\nafter_image(%d)\n", i));
362   while (i > 0) {
363     gifgetblock(buffer, i, grr);
364     i = gifgetbyte(grr);
365     GIF_DEBUG(("\nafter_image(%d)\n", i));
366   }
367 
368   /* zero-length block reached. */
369  zero_length_block: {
370       long delta = (long) (gfc->maximage - gfc->image) - (long) gfc->decodepos;
371       char buf[BUFSIZ];
372       if (delta > 0) {
373           sprintf(buf, "missing %ld %s of image data", delta,
374                   delta == 1 ? "pixel" : "pixels");
375           gif_read_error(gfc, 1, buf);
376           memset(&gfc->image[gfc->decodepos], 0, delta);
377       } else if (delta < -1) {
378           /* One pixel of superfluous data is OK; that could be the
379              code == next_code case. */
380           sprintf(buf, "%ld superfluous pixels of image data", -delta);
381           gif_read_error(gfc, 0, buf);
382       }
383   }
384 }
385 
386 
387 static Gif_Colormap *
read_color_table(int size,Gif_Reader * grr)388 read_color_table(int size, Gif_Reader *grr)
389 {
390   Gif_Colormap *gfcm = Gif_NewFullColormap(size, size);
391   Gif_Color *c;
392   if (!gfcm) return 0;
393 
394   GIF_DEBUG(("colormap(%d) ", size));
395   for (c = gfcm->col; size; size--, c++) {
396     c->gfc_red = gifgetbyte(grr);
397     c->gfc_green = gifgetbyte(grr);
398     c->gfc_blue = gifgetbyte(grr);
399     c->haspixel = 0;
400   }
401 
402   return gfcm;
403 }
404 
405 
406 static int
read_logical_screen_descriptor(Gif_Stream * gfs,Gif_Reader * grr)407 read_logical_screen_descriptor(Gif_Stream *gfs, Gif_Reader *grr)
408      /* returns 0 on memory error */
409 {
410   uint8_t packed;
411 
412   /* we don't care about logical screen width or height */
413   gfs->screen_width = gifgetunsigned(grr);
414   gfs->screen_height = gifgetunsigned(grr);
415 
416   packed = gifgetbyte(grr);
417   gfs->background = gifgetbyte(grr);
418 
419   /* don't care about pixel aspect ratio */
420   gifgetbyte(grr);
421 
422   if (packed & 0x80) { /* have a global color table */
423       int ncol = 1 << ((packed & 0x07) + 1);
424       gfs->global = read_color_table(ncol, grr);
425       if (!gfs->global) return 0;
426       gfs->global->refcount = 1;
427   } else
428       gfs->background = 256;
429 
430   return 1;
431 }
432 
433 
434 static int
read_compressed_image(Gif_Image * gfi,Gif_Reader * grr,int read_flags)435 read_compressed_image(Gif_Image *gfi, Gif_Reader *grr, int read_flags)
436 {
437   if (grr->is_record) {
438     const uint32_t image_pos = grr->pos;
439 
440     /* scan over image */
441     ++grr->pos; /* skip min code size */
442     while (grr->pos < grr->length) {
443         int amt = grr->v[grr->pos];
444         grr->pos += amt + 1;
445         if (amt == 0)
446             break;
447     }
448     if (grr->pos > grr->length)
449         grr->pos = grr->length;
450 
451     gfi->compressed_len = grr->pos - image_pos;
452     gfi->compressed_errors = 0;
453     if (read_flags & GIF_READ_CONST_RECORD) {
454       gfi->compressed = (uint8_t*) &grr->v[image_pos];
455       gfi->free_compressed = 0;
456     } else {
457       gfi->compressed = Gif_NewArray(uint8_t, gfi->compressed_len);
458       gfi->free_compressed = Gif_Free;
459       if (!gfi->compressed) return 0;
460       memcpy(gfi->compressed, &grr->v[image_pos], gfi->compressed_len);
461     }
462 
463   } else {
464     /* non-record; have to read it block by block. */
465     uint32_t comp_cap = 1024;
466     uint32_t comp_len;
467     uint8_t *comp = Gif_NewArray(uint8_t, comp_cap);
468     int i;
469     if (!comp) return 0;
470 
471     /* min code size */
472     i = gifgetbyte(grr);
473     comp[0] = i;
474     comp_len = 1;
475 
476     i = gifgetbyte(grr);
477     while (i > 0) {
478       /* add 2 before check so we don't have to check after loop when appending
479          0 block */
480       if (comp_len + i + 2 > comp_cap) {
481         comp_cap *= 2;
482         Gif_ReArray(comp, uint8_t, comp_cap);
483         if (!comp) return 0;
484       }
485       comp[comp_len] = i;
486       gifgetblock(comp + comp_len + 1, i, grr);
487       comp_len += i + 1;
488       i = gifgetbyte(grr);
489     }
490     comp[comp_len++] = 0;
491 
492     gfi->compressed_len = comp_len;
493     gfi->compressed_errors = 0;
494     gfi->compressed = comp;
495     gfi->free_compressed = Gif_Free;
496   }
497 
498   return 1;
499 }
500 
501 
502 static int
uncompress_image(Gif_Context * gfc,Gif_Image * gfi,Gif_Reader * grr)503 uncompress_image(Gif_Context *gfc, Gif_Image *gfi, Gif_Reader *grr)
504 {
505     int old_nerrors;
506     if (!Gif_CreateUncompressedImage(gfi, gfi->interlace))
507         return 0;
508     gfc->width = gfi->width;
509     gfc->height = gfi->height;
510     gfc->image = gfi->image_data;
511     gfc->maximage = gfi->image_data + (unsigned) gfi->width * (unsigned) gfi->height;
512     old_nerrors = gfc->errors[1];
513     read_image_data(gfc, grr);
514     gfi->compressed_errors = gfc->errors[1] - old_nerrors;
515     return 1;
516 }
517 
518 
519 int
Gif_FullUncompressImage(Gif_Stream * gfs,Gif_Image * gfi,Gif_ReadErrorHandler h)520 Gif_FullUncompressImage(Gif_Stream* gfs, Gif_Image* gfi,
521                         Gif_ReadErrorHandler h)
522 {
523   Gif_Context gfc;
524   Gif_Reader grr;
525   int ok = 0;
526 
527   /* return right away if image is already uncompressed. this might screw over
528      people who expect re-uncompressing to restore the compressed version. */
529   if (gfi->img)
530     return 2;
531   if (gfi->image_data)
532     /* we have uncompressed data, but not an 'img' array;
533        this shouldn't happen */
534     return 0;
535 
536   gfc.stream = gfs;
537   gfc.gfi = gfi;
538   gfc.prefix = Gif_NewArray(Gif_Code, GIF_MAX_CODE);
539   gfc.suffix = Gif_NewArray(uint8_t, GIF_MAX_CODE);
540   gfc.length = Gif_NewArray(uint16_t, GIF_MAX_CODE);
541   gfc.handler = h;
542   gfc.errors[0] = gfc.errors[1] = 0;
543 
544   if (gfc.prefix && gfc.suffix && gfc.length && gfi->compressed) {
545     make_data_reader(&grr, gfi->compressed, gfi->compressed_len);
546     ok = uncompress_image(&gfc, gfi, &grr);
547   }
548 
549   Gif_DeleteArray(gfc.prefix);
550   Gif_DeleteArray(gfc.suffix);
551   Gif_DeleteArray(gfc.length);
552   if (gfc.errors[0] || gfc.errors[1])
553       gif_read_error(&gfc, -1, 0);
554   return ok && !gfc.errors[1];
555 }
556 
557 
558 static int
read_image(Gif_Reader * grr,Gif_Context * gfc,Gif_Image * gfi,int read_flags)559 read_image(Gif_Reader *grr, Gif_Context *gfc, Gif_Image *gfi, int read_flags)
560      /* returns 0 on memory error */
561 {
562   uint8_t packed;
563 
564   gfi->left = gifgetunsigned(grr);
565   gfi->top = gifgetunsigned(grr);
566   gfi->width = gifgetunsigned(grr);
567   gfi->height = gifgetunsigned(grr);
568   /* Mainline GIF processors (Firefox, etc.) process missing width (height)
569      as screen_width (screen_height). */
570   if (gfi->width == 0)
571       gfi->width = gfc->stream->screen_width;
572   if (gfi->height == 0)
573       gfi->height = gfc->stream->screen_height;
574   /* If still zero, error. */
575   if (gfi->width == 0 || gfi->height == 0) {
576       gif_read_error(gfc, 1, "image has zero width and/or height");
577       Gif_MakeImageEmpty(gfi);
578       read_flags = 0;
579   }
580   /* If position out of range, error. */
581   if ((unsigned) gfi->left + (unsigned) gfi->width > 0xFFFF
582       || (unsigned) gfi->top + (unsigned) gfi->height > 0xFFFF) {
583       gif_read_error(gfc, 1, "image position and/or dimensions out of range");
584       Gif_MakeImageEmpty(gfi);
585       read_flags = 0;
586   }
587   GIF_DEBUG(("<%ux%u> ", gfi->width, gfi->height));
588 
589   packed = gifgetbyte(grr);
590   if (packed & 0x80) { /* have a local color table */
591     int ncol = 1 << ((packed & 0x07) + 1);
592     gfi->local = read_color_table(ncol, grr);
593     if (!gfi->local) return 0;
594     gfi->local->refcount = 1;
595   }
596 
597   gfi->interlace = (packed & 0x40) != 0;
598 
599   /* Keep the compressed data if asked */
600   if (read_flags & GIF_READ_COMPRESSED) {
601     if (!read_compressed_image(gfi, grr, read_flags))
602       return 0;
603     if (read_flags & GIF_READ_UNCOMPRESSED) {
604       Gif_Reader new_grr;
605       make_data_reader(&new_grr, gfi->compressed, gfi->compressed_len);
606       if (!uncompress_image(gfc, gfi, &new_grr))
607         return 0;
608     }
609 
610   } else if (read_flags & GIF_READ_UNCOMPRESSED) {
611     if (!uncompress_image(gfc, gfi, grr))
612       return 0;
613 
614   } else {
615     /* skip over the image */
616     uint8_t buffer[GIF_MAX_BLOCK];
617     int i = gifgetbyte(grr);
618     while (i > 0) {
619       gifgetblock(buffer, i, grr);
620       i = gifgetbyte(grr);
621     }
622   }
623 
624   return 1;
625 }
626 
627 
628 static void
read_graphic_control_extension(Gif_Context * gfc,Gif_Image * gfi,Gif_Reader * grr)629 read_graphic_control_extension(Gif_Context *gfc, Gif_Image *gfi,
630                                Gif_Reader *grr)
631 {
632   uint8_t len;
633   uint8_t crap[GIF_MAX_BLOCK];
634 
635   len = gifgetbyte(grr);
636 
637   if (len == 4) {
638     uint8_t packed = gifgetbyte(grr);
639     gfi->disposal = (packed >> 2) & 0x07;
640     gfi->delay = gifgetunsigned(grr);
641     gfi->transparent = gifgetbyte(grr);
642     if (!(packed & 0x01)) /* transparent color doesn't exist */
643       gfi->transparent = -1;
644     len -= 4;
645   }
646 
647   if (len > 0) {
648     gif_read_error(gfc, 1, "bad graphic extension");
649     gifgetblock(crap, len, grr);
650   }
651 
652   len = gifgetbyte(grr);
653   while (len > 0) {
654     gif_read_error(gfc, 1, "bad graphic extension");
655     gifgetblock(crap, len, grr);
656     len = gifgetbyte(grr);
657   }
658 }
659 
660 
661 static char *last_name;
662 
663 
664 static char *
suck_data(char * data,int * store_len,Gif_Reader * grr)665 suck_data(char *data, int *store_len, Gif_Reader *grr)
666 {
667   uint8_t len = gifgetbyte(grr);
668   int total_len = 0;
669 
670   while (len > 0) {
671     Gif_ReArray(data, char, total_len + len + 1);
672     if (!data) return 0;
673     gifgetblock((uint8_t *)data + total_len, len, grr);
674 
675     total_len += len;
676     data[total_len] = 0;
677 
678     len = gifgetbyte(grr);
679   }
680 
681   if (store_len) *store_len = total_len;
682   return data;
683 }
684 
685 
686 static int
read_unknown_extension(Gif_Context * gfc,Gif_Reader * grr,int kind,char * appname,int applength)687 read_unknown_extension(Gif_Context* gfc, Gif_Reader* grr,
688                        int kind, char* appname, int applength)
689 {
690     uint8_t block_len = gifgetbyte(grr);
691     uint8_t* data = 0;
692     int data_len = 0;
693     Gif_Extension *gfex = 0;
694 
695     while (block_len > 0) {
696         Gif_ReArray(data, uint8_t, data_len + block_len + 2);
697         if (!data)
698             goto done;
699         data[data_len] = block_len;
700         gifgetblock(data + data_len + 1, block_len, grr);
701         data_len += block_len + 1;
702         block_len = gifgetbyte(grr);
703     }
704 
705     if (data)
706         gfex = Gif_NewExtension(kind, appname, applength);
707     if (gfex) {
708         gfex->data = data;
709         gfex->free_data = Gif_Free;
710         gfex->length = data_len;
711         gfex->packetized = 1;
712         data[data_len] = 0;
713         Gif_AddExtension(gfc->stream, gfc->gfi, gfex);
714     }
715 
716  done:
717     if (!gfex)
718         Gif_DeleteArray(data);
719     while (block_len > 0) {
720         uint8_t buffer[GIF_MAX_BLOCK];
721         gifgetblock(buffer, block_len, grr);
722         block_len = gifgetbyte(grr);
723     }
724     return gfex != 0;
725 }
726 
727 
728 static int
read_application_extension(Gif_Context * gfc,Gif_Reader * grr)729 read_application_extension(Gif_Context *gfc, Gif_Reader *grr)
730 {
731   Gif_Stream *gfs = gfc->stream;
732   uint8_t buffer[GIF_MAX_BLOCK + 1];
733   uint8_t len = gifgetbyte(grr);
734   gifgetblock(buffer, len, grr);
735 
736   /* Read the Netscape loop extension. */
737   if (len == 11
738       && (memcmp(buffer, "NETSCAPE2.0", 11) == 0
739           || memcmp(buffer, "ANIMEXTS1.0", 11) == 0)) {
740 
741     len = gifgetbyte(grr);
742     if (len == 3) {
743       gifgetbyte(grr); /* throw away the 1 */
744       gfs->loopcount = gifgetunsigned(grr);
745       len = gifgetbyte(grr);
746       if (len)
747         gif_read_error(gfc, 1, "bad loop extension");
748     } else
749       gif_read_error(gfc, 1, "bad loop extension");
750 
751     while (len > 0) {
752       gifgetblock(buffer, len, grr);
753       len = gifgetbyte(grr);
754     }
755     return 1;
756 
757   } else
758     return read_unknown_extension(gfc, grr, 0xFF, (char*)buffer, len);
759 }
760 
761 
762 static int
read_comment_extension(Gif_Image * gfi,Gif_Reader * grr)763 read_comment_extension(Gif_Image *gfi, Gif_Reader *grr)
764 {
765   int len;
766   Gif_Comment *gfcom = gfi->comment;
767   char *m = suck_data(0, &len, grr);
768   if (m) {
769     if (!gfcom)
770       gfcom = gfi->comment = Gif_NewComment();
771     if (!gfcom || !Gif_AddCommentTake(gfcom, m, len))
772       return 0;
773   }
774   return 1;
775 }
776 
777 
778 static Gif_Stream *
read_gif(Gif_Reader * grr,int read_flags,const char * landmark,Gif_ReadErrorHandler handler)779 read_gif(Gif_Reader *grr, int read_flags,
780          const char* landmark, Gif_ReadErrorHandler handler)
781 {
782   Gif_Stream *gfs;
783   Gif_Image *gfi;
784   Gif_Context gfc;
785   int unknown_block_type = 0;
786 
787   if (gifgetc(grr) != 'G' ||
788       gifgetc(grr) != 'I' ||
789       gifgetc(grr) != 'F')
790     return 0;
791   (void)gifgetc(grr);
792   (void)gifgetc(grr);
793   (void)gifgetc(grr);
794 
795   gfs = Gif_NewStream();
796   gfi = Gif_NewImage();
797 
798   gfc.stream = gfs;
799   gfc.prefix = Gif_NewArray(Gif_Code, GIF_MAX_CODE);
800   gfc.suffix = Gif_NewArray(uint8_t, GIF_MAX_CODE);
801   gfc.length = Gif_NewArray(uint16_t, GIF_MAX_CODE);
802   gfc.handler = handler;
803   gfc.gfi = gfi;
804   gfc.errors[0] = gfc.errors[1] = 0;
805 
806   if (!gfs || !gfi || !gfc.prefix || !gfc.suffix || !gfc.length)
807     goto done;
808   gfs->landmark = landmark;
809 
810   GIF_DEBUG(("\nGIF "));
811   if (!read_logical_screen_descriptor(gfs, grr))
812     goto done;
813   GIF_DEBUG(("logscrdesc "));
814 
815   while (!gifeof(grr)) {
816 
817     uint8_t block = gifgetbyte(grr);
818 
819     switch (block) {
820 
821      case ',': /* image block */
822       GIF_DEBUG(("imageread %d ", gfs->nimages));
823 
824       gfi->identifier = last_name;
825       last_name = 0;
826       if (!Gif_AddImage(gfs, gfi))
827           goto done;
828       else if (!read_image(grr, &gfc, gfi, read_flags)) {
829           Gif_RemoveImage(gfs, gfs->nimages - 1);
830           gfi = 0;
831           goto done;
832       }
833 
834       gfc.gfi = gfi = Gif_NewImage();
835       if (!gfi)
836           goto done;
837       break;
838 
839      case ';': /* terminator */
840       GIF_DEBUG(("term\n"));
841       goto done;
842 
843      case '!': /* extension */
844       block = gifgetbyte(grr);
845       GIF_DEBUG(("ext(0x%02X) ", block));
846       switch (block) {
847 
848        case 0xF9:
849         read_graphic_control_extension(&gfc, gfi, grr);
850         break;
851 
852        case 0xCE:
853         last_name = suck_data(last_name, 0, grr);
854         break;
855 
856        case 0xFE:
857         if (!read_comment_extension(gfi, grr)) goto done;
858         break;
859 
860        case 0xFF:
861         read_application_extension(&gfc, grr);
862         break;
863 
864        default:
865         read_unknown_extension(&gfc, grr, block, 0, 0);
866         break;
867 
868       }
869       break;
870 
871      default:
872        if (!unknown_block_type) {
873          char buf[256];
874          sprintf(buf, "unknown block type %d at file offset %u", block, grr->pos - 1);
875          gif_read_error(&gfc, 1, buf);
876        }
877        if (++unknown_block_type > 20)
878          goto done;
879        break;
880 
881     }
882 
883   }
884 
885  done:
886 
887   /* Move comments and extensions after last image into stream. */
888   if (gfs && gfi) {
889       Gif_Extension* gfex;
890       gfs->end_comment = gfi->comment;
891       gfi->comment = 0;
892       gfs->end_extension_list = gfi->extension_list;
893       gfi->extension_list = 0;
894       for (gfex = gfs->end_extension_list; gfex; gfex = gfex->next)
895           gfex->image = NULL;
896   }
897 
898   Gif_DeleteImage(gfi);
899   Gif_DeleteArray(last_name);
900   Gif_DeleteArray(gfc.prefix);
901   Gif_DeleteArray(gfc.suffix);
902   Gif_DeleteArray(gfc.length);
903   gfc.gfi = 0;
904   last_name = 0;
905 
906   if (gfs)
907     gfs->errors = gfc.errors[1];
908   if (gfs && gfc.errors[1] == 0
909       && !(read_flags & GIF_READ_TRAILING_GARBAGE_OK)
910       && !grr->eofer(grr))
911       gif_read_error(&gfc, 0, "trailing garbage after GIF ignored");
912   /* finally, export last message */
913   gif_read_error(&gfc, -1, 0);
914 
915   return gfs;
916 }
917 
918 
919 Gif_Stream *
Gif_FullReadFile(FILE * f,int read_flags,const char * landmark,Gif_ReadErrorHandler h)920 Gif_FullReadFile(FILE *f, int read_flags,
921                  const char* landmark, Gif_ReadErrorHandler h)
922 {
923   Gif_Reader grr;
924   if (!f) return 0;
925   grr.f = f;
926   grr.pos = 0;
927   grr.is_record = 0;
928   grr.byte_getter = file_byte_getter;
929   grr.block_getter = file_block_getter;
930   grr.eofer = file_eofer;
931   return read_gif(&grr, read_flags, landmark, h);
932 }
933 
934 Gif_Stream *
Gif_FullReadRecord(const Gif_Record * gifrec,int read_flags,const char * landmark,Gif_ReadErrorHandler h)935 Gif_FullReadRecord(const Gif_Record *gifrec, int read_flags,
936                    const char* landmark, Gif_ReadErrorHandler h)
937 {
938   Gif_Reader grr;
939   if (!gifrec) return 0;
940   make_data_reader(&grr, gifrec->data, gifrec->length);
941   if (read_flags & GIF_READ_CONST_RECORD)
942     read_flags |= GIF_READ_COMPRESSED;
943   return read_gif(&grr, read_flags, landmark, h);
944 }
945 
946 
947 #undef Gif_ReadFile
948 #undef Gif_ReadRecord
949 
950 Gif_Stream *
Gif_ReadFile(FILE * f)951 Gif_ReadFile(FILE *f)
952 {
953   return Gif_FullReadFile(f, GIF_READ_UNCOMPRESSED, 0, 0);
954 }
955 
956 Gif_Stream *
Gif_ReadRecord(const Gif_Record * gifrec)957 Gif_ReadRecord(const Gif_Record *gifrec)
958 {
959   return Gif_FullReadRecord(gifrec, GIF_READ_UNCOMPRESSED, 0, 0);
960 }
961 
962 void
Gif_SetErrorHandler(Gif_ReadErrorHandler handler)963 Gif_SetErrorHandler(Gif_ReadErrorHandler handler) {
964     default_error_handler = handler;
965 }
966 
967 #ifdef __cplusplus
968 }
969 #endif
970