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