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