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