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