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