1 /******************************************************************************
2 
3 dgif_lib.c - GIF decoding
4 
5 The functions here and in egif_lib.c are partitioned carefully so that
6 if you only require one of read and write capability, only one of these
7 two modules will be linked.  Preserve this property!
8 
9 SPDX-License-Identifier: MIT
10 
11 *****************************************************************************/
12 
13 #include <stdlib.h>
14 #include <limits.h>
15 #include <stdint.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #ifdef _WIN32
21 #include <io.h>
22 #else
23 #include <unistd.h>
24 #endif /* _WIN32 */
25 
26 #include "gif_lib.h"
27 #include "gif_lib_private.h"
28 
29 /* compose unsigned little endian value */
30 #define UNSIGNED_LITTLE_ENDIAN(lo, hi)	((lo) | ((hi) << 8))
31 
32 /* avoid extra function call in case we use fread (TVT) */
InternalRead(GifFileType * gif,GifByteType * buf,int len)33 static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34     //fprintf(stderr, "### Read: %d\n", len);
35     return
36 	(((GifFilePrivateType*)gif->Private)->Read ?
37 	 ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) :
38 	 fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
39 }
40 
41 static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
42 static int DGifSetupDecompress(GifFileType *GifFile);
43 static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
44                               int LineLen);
45 static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
46 static int DGifDecompressInput(GifFileType *GifFile, int *Code);
47 static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
48                              GifByteType *NextByte);
49 
50 /******************************************************************************
51  Open a new GIF file for read, given by its name.
52  Returns dynamically allocated GifFileType pointer which serves as the GIF
53  info record.
54 ******************************************************************************/
55 GifFileType *
DGifOpenFileName(const char * FileName,int * Error)56 DGifOpenFileName(const char *FileName, int *Error)
57 {
58     int FileHandle;
59     GifFileType *GifFile;
60 
61     if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
62 	if (Error != NULL)
63 	    *Error = D_GIF_ERR_OPEN_FAILED;
64         return NULL;
65     }
66 
67     GifFile = DGifOpenFileHandle(FileHandle, Error);
68     return GifFile;
69 }
70 
71 /******************************************************************************
72  Update a new GIF file, given its file handle.
73  Returns dynamically allocated GifFileType pointer which serves as the GIF
74  info record.
75 ******************************************************************************/
76 GifFileType *
DGifOpenFileHandle(int FileHandle,int * Error)77 DGifOpenFileHandle(int FileHandle, int *Error)
78 {
79     char Buf[GIF_STAMP_LEN + 1];
80     GifFileType *GifFile;
81     GifFilePrivateType *Private;
82     FILE *f;
83 
84     GifFile = (GifFileType *)malloc(sizeof(GifFileType));
85     if (GifFile == NULL) {
86         if (Error != NULL)
87 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
88         (void)close(FileHandle);
89         return NULL;
90     }
91 
92     /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
93 
94     /* Belt and suspenders, in case the null pointer isn't zero */
95     GifFile->SavedImages = NULL;
96     GifFile->SColorMap = NULL;
97 
98     Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
99     if (Private == NULL) {
100         if (Error != NULL)
101 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
102         (void)close(FileHandle);
103         free((char *)GifFile);
104         return NULL;
105     }
106 
107     /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
108 
109 #ifdef _WIN32
110     _setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
111 #endif /* _WIN32 */
112 
113     f = fdopen(FileHandle, "rb");    /* Make it into a stream: */
114 
115     /*@-mustfreeonly@*/
116     GifFile->Private = (void *)Private;
117     Private->FileHandle = FileHandle;
118     Private->File = f;
119     Private->FileState = FILE_STATE_READ;
120     Private->Read = NULL;        /* don't use alternate input method (TVT) */
121     GifFile->UserData = NULL;    /* TVT */
122     /*@=mustfreeonly@*/
123 
124     /* Let's see if this is a GIF file: */
125     /* coverity[check_return] */
126     if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
127         if (Error != NULL)
128 	    *Error = D_GIF_ERR_READ_FAILED;
129         (void)fclose(f);
130         free((char *)Private);
131         free((char *)GifFile);
132         return NULL;
133     }
134 
135     /* Check for GIF prefix at start of file */
136     Buf[GIF_STAMP_LEN] = 0;
137     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
138         if (Error != NULL)
139 	    *Error = D_GIF_ERR_NOT_GIF_FILE;
140         (void)fclose(f);
141         free((char *)Private);
142         free((char *)GifFile);
143         return NULL;
144     }
145 
146     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
147         (void)fclose(f);
148         free((char *)Private);
149         free((char *)GifFile);
150         return NULL;
151     }
152 
153     GifFile->Error = 0;
154 
155     /* What version of GIF? */
156     Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
157 
158     return GifFile;
159 }
160 
161 /******************************************************************************
162  GifFileType constructor with user supplied input function (TVT)
163 ******************************************************************************/
164 GifFileType *
DGifOpen(void * userData,InputFunc readFunc,int * Error)165 DGifOpen(void *userData, InputFunc readFunc, int *Error)
166 {
167     char Buf[GIF_STAMP_LEN + 1];
168     GifFileType *GifFile;
169     GifFilePrivateType *Private;
170 
171     GifFile = (GifFileType *)malloc(sizeof(GifFileType));
172     if (GifFile == NULL) {
173         if (Error != NULL)
174 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
175         return NULL;
176     }
177 
178     memset(GifFile, '\0', sizeof(GifFileType));
179 
180     /* Belt and suspenders, in case the null pointer isn't zero */
181     GifFile->SavedImages = NULL;
182     GifFile->SColorMap = NULL;
183 
184     Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
185     if (!Private) {
186         if (Error != NULL)
187 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
188         free((char *)GifFile);
189         return NULL;
190     }
191     /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
192 
193     GifFile->Private = (void *)Private;
194     Private->FileHandle = 0;
195     Private->File = NULL;
196     Private->FileState = FILE_STATE_READ;
197 
198     Private->Read = readFunc;    /* TVT */
199     GifFile->UserData = userData;    /* TVT */
200 
201     /* Lets see if this is a GIF file: */
202     /* coverity[check_return] */
203     if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
204         if (Error != NULL)
205 	    *Error = D_GIF_ERR_READ_FAILED;
206         free((char *)Private);
207         free((char *)GifFile);
208         return NULL;
209     }
210 
211     /* Check for GIF prefix at start of file */
212     Buf[GIF_STAMP_LEN] = '\0';
213     if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
214         if (Error != NULL)
215 	    *Error = D_GIF_ERR_NOT_GIF_FILE;
216         free((char *)Private);
217         free((char *)GifFile);
218         return NULL;
219     }
220 
221     if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
222         free((char *)Private);
223         free((char *)GifFile);
224         if (Error != NULL)
225 	    *Error = D_GIF_ERR_NO_SCRN_DSCR;
226         return NULL;
227     }
228 
229     GifFile->Error = 0;
230 
231     /* What version of GIF? */
232     Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
233 
234     return GifFile;
235 }
236 
237 /******************************************************************************
238  This routine should be called before any other DGif calls. Note that
239  this routine is called automatically from DGif file open routines.
240 ******************************************************************************/
241 int
DGifGetScreenDesc(GifFileType * GifFile)242 DGifGetScreenDesc(GifFileType *GifFile)
243 {
244     int BitsPerPixel;
245     bool SortFlag;
246     GifByteType Buf[3];
247     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
248 
249     if (!IS_READABLE(Private)) {
250         /* This file was NOT open for reading: */
251         GifFile->Error = D_GIF_ERR_NOT_READABLE;
252         return GIF_ERROR;
253     }
254 
255     /* Put the screen descriptor into the file: */
256     if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
257         DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
258         return GIF_ERROR;
259 
260     if (InternalRead(GifFile, Buf, 3) != 3) {
261         GifFile->Error = D_GIF_ERR_READ_FAILED;
262 	GifFreeMapObject(GifFile->SColorMap);
263 	GifFile->SColorMap = NULL;
264         return GIF_ERROR;
265     }
266     GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
267     SortFlag = (Buf[0] & 0x08) != 0;
268     BitsPerPixel = (Buf[0] & 0x07) + 1;
269     GifFile->SBackGroundColor = Buf[1];
270     GifFile->AspectByte = Buf[2];
271     if (Buf[0] & 0x80) {    /* Do we have global color map? */
272 	int i;
273 
274         GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
275         if (GifFile->SColorMap == NULL) {
276             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
277             return GIF_ERROR;
278         }
279 
280         /* Get the global color map: */
281 	GifFile->SColorMap->SortFlag = SortFlag;
282         for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
283 	    /* coverity[check_return] */
284             if (InternalRead(GifFile, Buf, 3) != 3) {
285                 GifFreeMapObject(GifFile->SColorMap);
286                 GifFile->SColorMap = NULL;
287                 GifFile->Error = D_GIF_ERR_READ_FAILED;
288                 return GIF_ERROR;
289             }
290             GifFile->SColorMap->Colors[i].Red = Buf[0];
291             GifFile->SColorMap->Colors[i].Green = Buf[1];
292             GifFile->SColorMap->Colors[i].Blue = Buf[2];
293         }
294     } else {
295         GifFile->SColorMap = NULL;
296     }
297 
298     /*
299      * No check here for whether the background color is in range for the
300      * screen color map.  Possibly there should be.
301      */
302 
303     return GIF_OK;
304 }
305 
306 const char *
DGifGetGifVersion(GifFileType * GifFile)307 DGifGetGifVersion(GifFileType *GifFile)
308 {
309     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
310 
311     if (Private->gif89)
312 	return GIF89_STAMP;
313     else
314 	return GIF87_STAMP;
315 }
316 
317 /******************************************************************************
318  This routine should be called before any attempt to read an image.
319 ******************************************************************************/
320 int
DGifGetRecordType(GifFileType * GifFile,GifRecordType * Type)321 DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
322 {
323     GifByteType Buf;
324     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
325 
326     if (!IS_READABLE(Private)) {
327         /* This file was NOT open for reading: */
328         GifFile->Error = D_GIF_ERR_NOT_READABLE;
329         return GIF_ERROR;
330     }
331 
332     /* coverity[check_return] */
333     if (InternalRead(GifFile, &Buf, 1) != 1) {
334         GifFile->Error = D_GIF_ERR_READ_FAILED;
335         return GIF_ERROR;
336     }
337 
338     //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
339     switch (Buf) {
340       case DESCRIPTOR_INTRODUCER:
341           *Type = IMAGE_DESC_RECORD_TYPE;
342           break;
343       case EXTENSION_INTRODUCER:
344           *Type = EXTENSION_RECORD_TYPE;
345           break;
346       case TERMINATOR_INTRODUCER:
347           *Type = TERMINATE_RECORD_TYPE;
348           break;
349       default:
350           *Type = UNDEFINED_RECORD_TYPE;
351           GifFile->Error = D_GIF_ERR_WRONG_RECORD;
352           return GIF_ERROR;
353     }
354 
355     return GIF_OK;
356 }
357 
358 int
DGifGetImageHeader(GifFileType * GifFile)359 DGifGetImageHeader(GifFileType *GifFile)
360 {
361     unsigned int BitsPerPixel;
362     GifByteType Buf[3];
363     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
364 
365     if (!IS_READABLE(Private)) {
366         /* This file was NOT open for reading: */
367         GifFile->Error = D_GIF_ERR_NOT_READABLE;
368         return GIF_ERROR;
369     }
370 
371     if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
372         DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
373         DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
374         DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
375         return GIF_ERROR;
376     if (InternalRead(GifFile, Buf, 1) != 1) {
377         GifFile->Error = D_GIF_ERR_READ_FAILED;
378         GifFreeMapObject(GifFile->Image.ColorMap);
379         GifFile->Image.ColorMap = NULL;
380         return GIF_ERROR;
381     }
382     BitsPerPixel = (Buf[0] & 0x07) + 1;
383     GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
384 
385     /* Setup the colormap */
386     if (GifFile->Image.ColorMap) {
387         GifFreeMapObject(GifFile->Image.ColorMap);
388         GifFile->Image.ColorMap = NULL;
389     }
390     /* Does this image have local color map? */
391     if (Buf[0] & 0x80) {
392         unsigned int i;
393 
394         GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
395         if (GifFile->Image.ColorMap == NULL) {
396             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
397             return GIF_ERROR;
398         }
399 
400         /* Get the image local color map: */
401         for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
402             /* coverity[check_return] */
403             if (InternalRead(GifFile, Buf, 3) != 3) {
404                 GifFreeMapObject(GifFile->Image.ColorMap);
405                 GifFile->Error = D_GIF_ERR_READ_FAILED;
406                 GifFile->Image.ColorMap = NULL;
407                 return GIF_ERROR;
408             }
409             GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
410             GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
411             GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
412         }
413     }
414 
415     Private->PixelCount = (long)GifFile->Image.Width *
416        (long)GifFile->Image.Height;
417 
418     /* Reset decompress algorithm parameters. */
419     return DGifSetupDecompress(GifFile);
420 }
421 
422 /******************************************************************************
423  This routine should be called before any attempt to read an image.
424  Note it is assumed the Image desc. header has been read.
425 ******************************************************************************/
426 int
DGifGetImageDesc(GifFileType * GifFile)427 DGifGetImageDesc(GifFileType *GifFile)
428 {
429     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
430     SavedImage *sp;
431 
432     if (!IS_READABLE(Private)) {
433         /* This file was NOT open for reading: */
434         GifFile->Error = D_GIF_ERR_NOT_READABLE;
435         return GIF_ERROR;
436     }
437 
438     if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
439         return GIF_ERROR;
440     }
441 
442     if (GifFile->SavedImages) {
443         SavedImage* new_saved_images =
444             (SavedImage *)reallocarray(GifFile->SavedImages,
445                             (GifFile->ImageCount + 1), sizeof(SavedImage));
446         if (new_saved_images == NULL) {
447             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
448             return GIF_ERROR;
449         }
450         GifFile->SavedImages = new_saved_images;
451     } else {
452         if ((GifFile->SavedImages =
453              (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
454             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
455             return GIF_ERROR;
456         }
457     }
458 
459     sp = &GifFile->SavedImages[GifFile->ImageCount];
460     memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
461     if (GifFile->Image.ColorMap != NULL) {
462         sp->ImageDesc.ColorMap = GifMakeMapObject(
463                                  GifFile->Image.ColorMap->ColorCount,
464                                  GifFile->Image.ColorMap->Colors);
465         if (sp->ImageDesc.ColorMap == NULL) {
466             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
467             return GIF_ERROR;
468         }
469     }
470     sp->RasterBits = (unsigned char *)NULL;
471     sp->ExtensionBlockCount = 0;
472     sp->ExtensionBlocks = (ExtensionBlock *) NULL;
473 
474     GifFile->ImageCount++;
475 
476     return GIF_OK;
477 }
478 
479 /******************************************************************************
480  Get one full scanned line (Line) of length LineLen from GIF file.
481 ******************************************************************************/
482 int
DGifGetLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)483 DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
484 {
485     GifByteType *Dummy;
486     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
487 
488     if (!IS_READABLE(Private)) {
489         /* This file was NOT open for reading: */
490         GifFile->Error = D_GIF_ERR_NOT_READABLE;
491         return GIF_ERROR;
492     }
493 
494     if (!LineLen)
495         LineLen = GifFile->Image.Width;
496 
497     if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498         GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
499         return GIF_ERROR;
500     }
501 
502     if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503         if (Private->PixelCount == 0) {
504             /* We probably won't be called any more, so let's clean up
505              * everything before we return: need to flush out all the
506              * rest of image until an empty block (size 0)
507              * detected. We use GetCodeNext.
508 	     */
509             do
510                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
511                     return GIF_ERROR;
512             while (Dummy != NULL) ;
513         }
514         return GIF_OK;
515     } else
516         return GIF_ERROR;
517 }
518 
519 /******************************************************************************
520  Put one pixel (Pixel) into GIF file.
521 ******************************************************************************/
522 int
DGifGetPixel(GifFileType * GifFile,GifPixelType Pixel)523 DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
524 {
525     GifByteType *Dummy;
526     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
527 
528     if (!IS_READABLE(Private)) {
529         /* This file was NOT open for reading: */
530         GifFile->Error = D_GIF_ERR_NOT_READABLE;
531         return GIF_ERROR;
532     }
533     if (--Private->PixelCount > 0xffff0000UL)
534     {
535         GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
536         return GIF_ERROR;
537     }
538 
539     if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
540         if (Private->PixelCount == 0) {
541             /* We probably won't be called any more, so let's clean up
542              * everything before we return: need to flush out all the
543              * rest of image until an empty block (size 0)
544              * detected. We use GetCodeNext.
545 	     */
546             do
547                 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
548                     return GIF_ERROR;
549             while (Dummy != NULL) ;
550         }
551         return GIF_OK;
552     } else
553         return GIF_ERROR;
554 }
555 
556 /******************************************************************************
557  Get an extension block (see GIF manual) from GIF file. This routine only
558  returns the first data block, and DGifGetExtensionNext should be called
559  after this one until NULL extension is returned.
560  The Extension should NOT be freed by the user (not dynamically allocated).
561  Note it is assumed the Extension description header has been read.
562 ******************************************************************************/
563 int
DGifGetExtension(GifFileType * GifFile,int * ExtCode,GifByteType ** Extension)564 DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
565 {
566     GifByteType Buf;
567     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
568 
569     //fprintf(stderr, "### -> DGifGetExtension:\n");
570     if (!IS_READABLE(Private)) {
571         /* This file was NOT open for reading: */
572         GifFile->Error = D_GIF_ERR_NOT_READABLE;
573         return GIF_ERROR;
574     }
575 
576     /* coverity[check_return] */
577     if (InternalRead(GifFile, &Buf, 1) != 1) {
578         GifFile->Error = D_GIF_ERR_READ_FAILED;
579         return GIF_ERROR;
580     }
581     *ExtCode = Buf;
582     //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
583 
584     return DGifGetExtensionNext(GifFile, Extension);
585 }
586 
587 /******************************************************************************
588  Get a following extension block (see GIF manual) from GIF file. This
589  routine should be called until NULL Extension is returned.
590  The Extension should NOT be freed by the user (not dynamically allocated).
591 ******************************************************************************/
592 int
DGifGetExtensionNext(GifFileType * GifFile,GifByteType ** Extension)593 DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
594 {
595     GifByteType Buf;
596     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
597 
598     //fprintf(stderr, "### -> DGifGetExtensionNext\n");
599     if (InternalRead(GifFile, &Buf, 1) != 1) {
600         GifFile->Error = D_GIF_ERR_READ_FAILED;
601         return GIF_ERROR;
602     }
603     //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
604 
605     if (Buf > 0) {
606         *Extension = Private->Buf;    /* Use private unused buffer. */
607         (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
608 	/* coverity[tainted_data,check_return] */
609         if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
610             GifFile->Error = D_GIF_ERR_READ_FAILED;
611             return GIF_ERROR;
612         }
613     } else
614         *Extension = NULL;
615     //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
616 
617     return GIF_OK;
618 }
619 
620 /******************************************************************************
621  Extract a Graphics Control Block from raw extension data
622 ******************************************************************************/
623 
DGifExtensionToGCB(const size_t GifExtensionLength,const GifByteType * GifExtension,GraphicsControlBlock * GCB)624 int DGifExtensionToGCB(const size_t GifExtensionLength,
625 		       const GifByteType *GifExtension,
626 		       GraphicsControlBlock *GCB)
627 {
628     if (GifExtensionLength != 4) {
629 	return GIF_ERROR;
630     }
631 
632     GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
633     GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
634     GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
635     if (GifExtension[0] & 0x01)
636 	GCB->TransparentColor = (int)GifExtension[3];
637     else
638 	GCB->TransparentColor = NO_TRANSPARENT_COLOR;
639 
640     return GIF_OK;
641 }
642 
643 /******************************************************************************
644  Extract the Graphics Control Block for a saved image, if it exists.
645 ******************************************************************************/
646 
DGifSavedExtensionToGCB(GifFileType * GifFile,int ImageIndex,GraphicsControlBlock * GCB)647 int DGifSavedExtensionToGCB(GifFileType *GifFile,
648 			    int ImageIndex, GraphicsControlBlock *GCB)
649 {
650     int i;
651 
652     if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
653 	return GIF_ERROR;
654 
655     GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
656     GCB->UserInputFlag = false;
657     GCB->DelayTime = 0;
658     GCB->TransparentColor = NO_TRANSPARENT_COLOR;
659 
660     for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
661 	ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
662 	if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
663 	    return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
664     }
665 
666     return GIF_ERROR;
667 }
668 
669 /******************************************************************************
670  This routine should be called last, to close the GIF file.
671 ******************************************************************************/
672 int
DGifCloseFile(GifFileType * GifFile,int * ErrorCode)673 DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
674 {
675     GifFilePrivateType *Private;
676 
677     if (GifFile == NULL || GifFile->Private == NULL)
678         return GIF_ERROR;
679 
680     if (GifFile->Image.ColorMap) {
681         GifFreeMapObject(GifFile->Image.ColorMap);
682         GifFile->Image.ColorMap = NULL;
683     }
684 
685     if (GifFile->SColorMap) {
686         GifFreeMapObject(GifFile->SColorMap);
687         GifFile->SColorMap = NULL;
688     }
689 
690     if (GifFile->SavedImages) {
691         GifFreeSavedImages(GifFile);
692         GifFile->SavedImages = NULL;
693     }
694 
695     GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
696 
697     Private = (GifFilePrivateType *) GifFile->Private;
698 
699     if (!IS_READABLE(Private)) {
700         /* This file was NOT open for reading: */
701 	if (ErrorCode != NULL)
702 	    *ErrorCode = D_GIF_ERR_NOT_READABLE;
703 	free((char *)GifFile->Private);
704 	free(GifFile);
705         return GIF_ERROR;
706     }
707 
708     if (Private->File && (fclose(Private->File) != 0)) {
709 	if (ErrorCode != NULL)
710 	    *ErrorCode = D_GIF_ERR_CLOSE_FAILED;
711 	free((char *)GifFile->Private);
712 	free(GifFile);
713         return GIF_ERROR;
714     }
715 
716     free((char *)GifFile->Private);
717     free(GifFile);
718     if (ErrorCode != NULL)
719 	*ErrorCode = D_GIF_SUCCEEDED;
720     return GIF_OK;
721 }
722 
723 /******************************************************************************
724  Get 2 bytes (word) from the given file:
725 ******************************************************************************/
726 static int
DGifGetWord(GifFileType * GifFile,GifWord * Word)727 DGifGetWord(GifFileType *GifFile, GifWord *Word)
728 {
729     unsigned char c[2];
730 
731     /* coverity[check_return] */
732     if (InternalRead(GifFile, c, 2) != 2) {
733         GifFile->Error = D_GIF_ERR_READ_FAILED;
734         return GIF_ERROR;
735     }
736 
737     *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
738     return GIF_OK;
739 }
740 
741 /******************************************************************************
742  Get the image code in compressed form.  This routine can be called if the
743  information needed to be piped out as is. Obviously this is much faster
744  than decoding and encoding again. This routine should be followed by calls
745  to DGifGetCodeNext, until NULL block is returned.
746  The block should NOT be freed by the user (not dynamically allocated).
747 ******************************************************************************/
748 int
DGifGetCode(GifFileType * GifFile,int * CodeSize,GifByteType ** CodeBlock)749 DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
750 {
751     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
752 
753     if (!IS_READABLE(Private)) {
754         /* This file was NOT open for reading: */
755         GifFile->Error = D_GIF_ERR_NOT_READABLE;
756         return GIF_ERROR;
757     }
758 
759     *CodeSize = Private->BitsPerPixel;
760 
761     return DGifGetCodeNext(GifFile, CodeBlock);
762 }
763 
764 /******************************************************************************
765  Continue to get the image code in compressed form. This routine should be
766  called until NULL block is returned.
767  The block should NOT be freed by the user (not dynamically allocated).
768 ******************************************************************************/
769 int
DGifGetCodeNext(GifFileType * GifFile,GifByteType ** CodeBlock)770 DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
771 {
772     GifByteType Buf;
773     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
774 
775     /* coverity[tainted_data_argument] */
776     /* coverity[check_return] */
777     if (InternalRead(GifFile, &Buf, 1) != 1) {
778         GifFile->Error = D_GIF_ERR_READ_FAILED;
779         return GIF_ERROR;
780     }
781 
782     /* coverity[lower_bounds] */
783     if (Buf > 0) {
784         *CodeBlock = Private->Buf;    /* Use private unused buffer. */
785         (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
786 	/* coverity[tainted_data] */
787         if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
788             GifFile->Error = D_GIF_ERR_READ_FAILED;
789             return GIF_ERROR;
790         }
791     } else {
792         *CodeBlock = NULL;
793         Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
794         Private->PixelCount = 0;    /* And local info. indicate image read. */
795     }
796 
797     return GIF_OK;
798 }
799 
800 /******************************************************************************
801  Setup the LZ decompression for this image:
802 ******************************************************************************/
803 static int
DGifSetupDecompress(GifFileType * GifFile)804 DGifSetupDecompress(GifFileType *GifFile)
805 {
806     int i, BitsPerPixel;
807     GifByteType CodeSize;
808     GifPrefixType *Prefix;
809     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
810 
811     /* coverity[check_return] */
812     if (InternalRead(GifFile, &CodeSize, 1) < 1) {    /* Read Code size from file. */
813 	return GIF_ERROR;    /* Failed to read Code size. */
814     }
815     BitsPerPixel = CodeSize;
816 
817     /* this can only happen on a severely malformed GIF */
818     if (BitsPerPixel > 8) {
819 	GifFile->Error = D_GIF_ERR_READ_FAILED;	/* somewhat bogus error code */
820 	return GIF_ERROR;    /* Failed to read Code size. */
821     }
822 
823     Private->Buf[0] = 0;    /* Input Buffer empty. */
824     Private->BitsPerPixel = BitsPerPixel;
825     Private->ClearCode = (1 << BitsPerPixel);
826     Private->EOFCode = Private->ClearCode + 1;
827     Private->RunningCode = Private->EOFCode + 1;
828     Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
829     Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
830     Private->StackPtr = 0;    /* No pixels on the pixel stack. */
831     Private->LastCode = NO_SUCH_CODE;
832     Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
833     Private->CrntShiftDWord = 0;
834 
835     Prefix = Private->Prefix;
836     for (i = 0; i <= LZ_MAX_CODE; i++)
837         Prefix[i] = NO_SUCH_CODE;
838 
839     return GIF_OK;
840 }
841 
842 /******************************************************************************
843  The LZ decompression routine:
844  This version decompress the given GIF file into Line of length LineLen.
845  This routine can be called few times (one per scan line, for example), in
846  order the complete the whole image.
847 ******************************************************************************/
848 static int
DGifDecompressLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)849 DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
850 {
851     int i = 0;
852     int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
853     GifByteType *Stack, *Suffix;
854     GifPrefixType *Prefix;
855     GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
856 
857     StackPtr = Private->StackPtr;
858     Prefix = Private->Prefix;
859     Suffix = Private->Suffix;
860     Stack = Private->Stack;
861     EOFCode = Private->EOFCode;
862     ClearCode = Private->ClearCode;
863     LastCode = Private->LastCode;
864 
865     if (StackPtr > LZ_MAX_CODE) {
866         return GIF_ERROR;
867     }
868 
869     if (StackPtr != 0) {
870         /* Let pop the stack off before continueing to read the GIF file: */
871         while (StackPtr != 0 && i < LineLen)
872             Line[i++] = Stack[--StackPtr];
873     }
874 
875     while (i < LineLen) {    /* Decode LineLen items. */
876         if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
877             return GIF_ERROR;
878 
879         if (CrntCode == EOFCode) {
880             /* Note however that usually we will not be here as we will stop
881              * decoding as soon as we got all the pixel, or EOF code will
882              * not be read at all, and DGifGetLine/Pixel clean everything.  */
883 	    GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
884 	    return GIF_ERROR;
885         } else if (CrntCode == ClearCode) {
886             /* We need to start over again: */
887             for (j = 0; j <= LZ_MAX_CODE; j++)
888                 Prefix[j] = NO_SUCH_CODE;
889             Private->RunningCode = Private->EOFCode + 1;
890             Private->RunningBits = Private->BitsPerPixel + 1;
891             Private->MaxCode1 = 1 << Private->RunningBits;
892             LastCode = Private->LastCode = NO_SUCH_CODE;
893         } else {
894             /* Its regular code - if in pixel range simply add it to output
895              * stream, otherwise trace to codes linked list until the prefix
896              * is in pixel range: */
897             if (CrntCode < ClearCode) {
898                 /* This is simple - its pixel scalar, so add it to output: */
899                 Line[i++] = CrntCode;
900             } else {
901                 /* Its a code to needed to be traced: trace the linked list
902                  * until the prefix is a pixel, while pushing the suffix
903                  * pixels on our stack. If we done, pop the stack in reverse
904                  * (thats what stack is good for!) order to output.  */
905                 if (Prefix[CrntCode] == NO_SUCH_CODE) {
906                     CrntPrefix = LastCode;
907 
908                     /* Only allowed if CrntCode is exactly the running code:
909                      * In that case CrntCode = XXXCode, CrntCode or the
910                      * prefix code is last code and the suffix char is
911                      * exactly the prefix of last code! */
912                     if (CrntCode == Private->RunningCode - 2) {
913                         Suffix[Private->RunningCode - 2] =
914                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
915                                                                  LastCode,
916                                                                  ClearCode);
917                     } else {
918                         Suffix[Private->RunningCode - 2] =
919                            Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
920                                                                  CrntCode,
921                                                                  ClearCode);
922                     }
923                 } else
924                     CrntPrefix = CrntCode;
925 
926                 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
927                  * during the trace. As we might loop forever, in case of
928                  * defective image, we use StackPtr as loop counter and stop
929                  * before overflowing Stack[]. */
930                 while (StackPtr < LZ_MAX_CODE &&
931                        CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
932                     Stack[StackPtr++] = Suffix[CrntPrefix];
933                     CrntPrefix = Prefix[CrntPrefix];
934                 }
935                 if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
936                     GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
937                     return GIF_ERROR;
938                 }
939                 /* Push the last character on stack: */
940                 Stack[StackPtr++] = CrntPrefix;
941 
942                 /* Now lets pop all the stack into output: */
943                 while (StackPtr != 0 && i < LineLen)
944                     Line[i++] = Stack[--StackPtr];
945             }
946             if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
947                 Prefix[Private->RunningCode - 2] = LastCode;
948 
949                 if (CrntCode == Private->RunningCode - 2) {
950                     /* Only allowed if CrntCode is exactly the running code:
951                      * In that case CrntCode = XXXCode, CrntCode or the
952                      * prefix code is last code and the suffix char is
953                      * exactly the prefix of last code! */
954                     Suffix[Private->RunningCode - 2] =
955                        DGifGetPrefixChar(Prefix, LastCode, ClearCode);
956                 } else {
957                     Suffix[Private->RunningCode - 2] =
958                        DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
959                 }
960             }
961             LastCode = CrntCode;
962         }
963     }
964 
965     Private->LastCode = LastCode;
966     Private->StackPtr = StackPtr;
967 
968     return GIF_OK;
969 }
970 
971 /******************************************************************************
972  Routine to trace the Prefixes linked list until we get a prefix which is
973  not code, but a pixel value (less than ClearCode). Returns that pixel value.
974  If image is defective, we might loop here forever, so we limit the loops to
975  the maximum possible if image O.k. - LZ_MAX_CODE times.
976 ******************************************************************************/
977 static int
DGifGetPrefixChar(GifPrefixType * Prefix,int Code,int ClearCode)978 DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
979 {
980     int i = 0;
981 
982     while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
983         if (Code > LZ_MAX_CODE) {
984             return NO_SUCH_CODE;
985         }
986         Code = Prefix[Code];
987     }
988     return Code;
989 }
990 
991 /******************************************************************************
992  Interface for accessing the LZ codes directly. Set Code to the real code
993  (12bits), or to -1 if EOF code is returned.
994 ******************************************************************************/
995 int
DGifGetLZCodes(GifFileType * GifFile,int * Code)996 DGifGetLZCodes(GifFileType *GifFile, int *Code)
997 {
998     GifByteType *CodeBlock;
999     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1000 
1001     if (!IS_READABLE(Private)) {
1002         /* This file was NOT open for reading: */
1003         GifFile->Error = D_GIF_ERR_NOT_READABLE;
1004         return GIF_ERROR;
1005     }
1006 
1007     if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
1008         return GIF_ERROR;
1009 
1010     if (*Code == Private->EOFCode) {
1011         /* Skip rest of codes (hopefully only NULL terminating block): */
1012         do {
1013             if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1014                 return GIF_ERROR;
1015         } while (CodeBlock != NULL) ;
1016 
1017         *Code = -1;
1018     } else if (*Code == Private->ClearCode) {
1019         /* We need to start over again: */
1020         Private->RunningCode = Private->EOFCode + 1;
1021         Private->RunningBits = Private->BitsPerPixel + 1;
1022         Private->MaxCode1 = 1 << Private->RunningBits;
1023     }
1024 
1025     return GIF_OK;
1026 }
1027 
1028 /******************************************************************************
1029  The LZ decompression input routine:
1030  This routine is responsable for the decompression of the bit stream from
1031  8 bits (bytes) packets, into the real codes.
1032  Returns GIF_OK if read successfully.
1033 ******************************************************************************/
1034 static int
DGifDecompressInput(GifFileType * GifFile,int * Code)1035 DGifDecompressInput(GifFileType *GifFile, int *Code)
1036 {
1037     static const unsigned short CodeMasks[] = {
1038 	0x0000, 0x0001, 0x0003, 0x0007,
1039 	0x000f, 0x001f, 0x003f, 0x007f,
1040 	0x00ff, 0x01ff, 0x03ff, 0x07ff,
1041 	0x0fff
1042     };
1043 
1044     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1045 
1046     GifByteType NextByte;
1047 
1048     /* The image can't contain more than LZ_BITS per code. */
1049     if (Private->RunningBits > LZ_BITS) {
1050         GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1051         return GIF_ERROR;
1052     }
1053 
1054     while (Private->CrntShiftState < Private->RunningBits) {
1055         /* Needs to get more bytes from input stream for next code: */
1056         if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
1057             return GIF_ERROR;
1058         }
1059         Private->CrntShiftDWord |=
1060 	    ((unsigned long)NextByte) << Private->CrntShiftState;
1061         Private->CrntShiftState += 8;
1062     }
1063     *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1064 
1065     Private->CrntShiftDWord >>= Private->RunningBits;
1066     Private->CrntShiftState -= Private->RunningBits;
1067 
1068     /* If code cannot fit into RunningBits bits, must raise its size. Note
1069      * however that codes above 4095 are used for special signaling.
1070      * If we're using LZ_BITS bits already and we're at the max code, just
1071      * keep using the table as it is, don't increment Private->RunningCode.
1072      */
1073     if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1074 	++Private->RunningCode > Private->MaxCode1 &&
1075 	Private->RunningBits < LZ_BITS) {
1076         Private->MaxCode1 <<= 1;
1077         Private->RunningBits++;
1078     }
1079     return GIF_OK;
1080 }
1081 
1082 /******************************************************************************
1083  This routines read one GIF data block at a time and buffers it internally
1084  so that the decompression routine could access it.
1085  The routine returns the next byte from its internal buffer (or read next
1086  block in if buffer empty) and returns GIF_OK if succesful.
1087 ******************************************************************************/
1088 static int
DGifBufferedInput(GifFileType * GifFile,GifByteType * Buf,GifByteType * NextByte)1089 DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
1090 {
1091     if (Buf[0] == 0) {
1092         /* Needs to read the next buffer - this one is empty: */
1093 	/* coverity[check_return] */
1094         if (InternalRead(GifFile, Buf, 1) != 1) {
1095             GifFile->Error = D_GIF_ERR_READ_FAILED;
1096             return GIF_ERROR;
1097         }
1098         /* There shouldn't be any empty data blocks here as the LZW spec
1099          * says the LZW termination code should come first.  Therefore we
1100          * shouldn't be inside this routine at that point.
1101          */
1102         if (Buf[0] == 0) {
1103             GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1104             return GIF_ERROR;
1105         }
1106         if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1107             GifFile->Error = D_GIF_ERR_READ_FAILED;
1108             return GIF_ERROR;
1109         }
1110         *NextByte = Buf[1];
1111         Buf[1] = 2;    /* We use now the second place as last char read! */
1112         Buf[0]--;
1113     } else {
1114         *NextByte = Buf[Buf[1]++];
1115         Buf[0]--;
1116     }
1117 
1118     return GIF_OK;
1119 }
1120 
1121 /******************************************************************************
1122  This routine reads an entire GIF into core, hanging all its state info off
1123  the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
1124  first to initialize I/O.  Its inverse is EGifSpew().
1125 *******************************************************************************/
1126 int
DGifSlurp(GifFileType * GifFile)1127 DGifSlurp(GifFileType *GifFile)
1128 {
1129     size_t ImageSize;
1130     GifRecordType RecordType;
1131     SavedImage *sp;
1132     GifByteType *ExtData;
1133     int ExtFunction;
1134 
1135     GifFile->ExtensionBlocks = NULL;
1136     GifFile->ExtensionBlockCount = 0;
1137 
1138     do {
1139         if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1140             return (GIF_ERROR);
1141 
1142         switch (RecordType) {
1143           case IMAGE_DESC_RECORD_TYPE:
1144               if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1145                   return (GIF_ERROR);
1146 
1147               sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1148               /* Allocate memory for the image */
1149               if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
1150                       sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1151                   return GIF_ERROR;
1152               }
1153               ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1154 
1155               if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1156                   return GIF_ERROR;
1157               }
1158               sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
1159                       sizeof(GifPixelType));
1160 
1161               if (sp->RasterBits == NULL) {
1162                   return GIF_ERROR;
1163               }
1164 
1165 	      if (sp->ImageDesc.Interlace) {
1166 		  int i, j;
1167 		   /*
1168 		    * The way an interlaced image should be read -
1169 		    * offsets and jumps...
1170 		    */
1171 		  int InterlacedOffset[] = { 0, 4, 2, 1 };
1172 		  int InterlacedJumps[] = { 8, 8, 4, 2 };
1173 		  /* Need to perform 4 passes on the image */
1174 		  for (i = 0; i < 4; i++)
1175 		      for (j = InterlacedOffset[i];
1176 			   j < sp->ImageDesc.Height;
1177 			   j += InterlacedJumps[i]) {
1178 			  if (DGifGetLine(GifFile,
1179 					  sp->RasterBits+j*sp->ImageDesc.Width,
1180 					  sp->ImageDesc.Width) == GIF_ERROR)
1181 			      return GIF_ERROR;
1182 		      }
1183 	      }
1184 	      else {
1185 		  if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1186 		      return (GIF_ERROR);
1187 	      }
1188 
1189               if (GifFile->ExtensionBlocks) {
1190                   sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1191                   sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1192 
1193                   GifFile->ExtensionBlocks = NULL;
1194                   GifFile->ExtensionBlockCount = 0;
1195               }
1196               break;
1197 
1198           case EXTENSION_RECORD_TYPE:
1199               if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1200                   return (GIF_ERROR);
1201 	      /* Create an extension block with our data */
1202               if (ExtData != NULL) {
1203 		  if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1204 					   &GifFile->ExtensionBlocks,
1205 					   ExtFunction, ExtData[0], &ExtData[1])
1206 		      == GIF_ERROR)
1207 		      return (GIF_ERROR);
1208 	      }
1209               for (;;) {
1210                   if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1211                       return (GIF_ERROR);
1212 		  if (ExtData == NULL)
1213 		      break;
1214                   /* Continue the extension block */
1215 		  if (ExtData != NULL)
1216 		      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1217 					       &GifFile->ExtensionBlocks,
1218 					       CONTINUE_EXT_FUNC_CODE,
1219 					       ExtData[0], &ExtData[1]) == GIF_ERROR)
1220                       return (GIF_ERROR);
1221               }
1222               break;
1223 
1224           case TERMINATE_RECORD_TYPE:
1225               break;
1226 
1227           default:    /* Should be trapped by DGifGetRecordType */
1228               break;
1229         }
1230     } while (RecordType != TERMINATE_RECORD_TYPE);
1231 
1232     /* Sanity check for corrupted file */
1233     if (GifFile->ImageCount == 0) {
1234 	GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1235 	return(GIF_ERROR);
1236     }
1237 
1238     return (GIF_OK);
1239 }
1240 
1241 /* end */
1242