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