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