Coverage Report

Created: 2023-03-26 07:33

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