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