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
162k
#define UNSIGNED_LITTLE_ENDIAN(lo, hi)  ((lo) | ((hi) << 8))
31
32
/* avoid extra function call in case we use fread (TVT) */
33
576k
static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34
    //fprintf(stderr, "### Read: %d\n", len);
35
576k
    return 
36
576k
  (((GifFilePrivateType*)gif->Private)->Read ?
37
576k
   ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) : 
38
576k
   fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
39
576k
}
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.02k
{
167
1.02k
    char Buf[GIF_STAMP_LEN + 1];
168
1.02k
    GifFileType *GifFile;
169
1.02k
    GifFilePrivateType *Private;
170
171
1.02k
    GifFile = (GifFileType *)malloc(sizeof(GifFileType));
172
1.02k
    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.02k
    memset(GifFile, '\0', sizeof(GifFileType));
179
180
    /* Belt and suspenders, in case the null pointer isn't zero */
181
1.02k
    GifFile->SavedImages = NULL;
182
1.02k
    GifFile->SColorMap = NULL;
183
184
1.02k
    Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
185
1.02k
    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.02k
    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
192
193
1.02k
    GifFile->Private = (void *)Private;
194
1.02k
    Private->FileHandle = 0;
195
1.02k
    Private->File = NULL;
196
1.02k
    Private->FileState = FILE_STATE_READ;
197
198
1.02k
    Private->Read = readFunc;    /* TVT */
199
1.02k
    GifFile->UserData = userData;    /* TVT */
200
201
    /* Lets see if this is a GIF file: */
202
    /* coverity[check_return] */
203
1.02k
    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
204
4
        if (Error != NULL)
205
4
      *Error = D_GIF_ERR_READ_FAILED;
206
4
        free((char *)Private);
207
4
        free((char *)GifFile);
208
4
        return NULL;
209
4
    }
210
211
    /* Check for GIF prefix at start of file */
212
1.01k
    Buf[GIF_STAMP_LEN] = '\0';
213
1.01k
    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
214
34
        if (Error != NULL)
215
34
      *Error = D_GIF_ERR_NOT_GIF_FILE;
216
34
        free((char *)Private);
217
34
        free((char *)GifFile);
218
34
        return NULL;
219
34
    }
220
221
984
    if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
222
30
        free((char *)Private);
223
30
        free((char *)GifFile);
224
30
        if (Error != NULL)
225
30
      *Error = D_GIF_ERR_NO_SCRN_DSCR;
226
30
        return NULL;
227
30
    }
228
229
954
    GifFile->Error = 0;
230
231
    /* What version of GIF? */
232
954
    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
233
234
954
    return GifFile;
235
984
}
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
984
{
244
984
    int BitsPerPixel;
245
984
    bool SortFlag;
246
984
    GifByteType Buf[3];
247
984
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
248
249
984
    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
984
    if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
257
984
        DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
258
4
        return GIF_ERROR;
259
260
980
    if (InternalRead(GifFile, Buf, 3) != 3) {
261
3
        GifFile->Error = D_GIF_ERR_READ_FAILED;
262
3
  GifFreeMapObject(GifFile->SColorMap);
263
3
  GifFile->SColorMap = NULL;
264
3
        return GIF_ERROR;
265
3
    }
266
977
    GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
267
977
    SortFlag = (Buf[0] & 0x08) != 0;
268
977
    BitsPerPixel = (Buf[0] & 0x07) + 1;
269
977
    GifFile->SBackGroundColor = Buf[1];
270
977
    GifFile->AspectByte = Buf[2]; 
271
977
    if (Buf[0] & 0x80) {    /* Do we have global color map? */
272
94
  int i;
273
274
94
        GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
275
94
        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
94
  GifFile->SColorMap->SortFlag = SortFlag;
282
1.12k
        for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
283
      /* coverity[check_return] */
284
1.05k
            if (InternalRead(GifFile, Buf, 3) != 3) {
285
23
                GifFreeMapObject(GifFile->SColorMap);
286
23
                GifFile->SColorMap = NULL;
287
23
                GifFile->Error = D_GIF_ERR_READ_FAILED;
288
23
                return GIF_ERROR;
289
23
            }
290
1.03k
            GifFile->SColorMap->Colors[i].Red = Buf[0];
291
1.03k
            GifFile->SColorMap->Colors[i].Green = Buf[1];
292
1.03k
            GifFile->SColorMap->Colors[i].Blue = Buf[2];
293
1.03k
        }
294
883
    } else {
295
883
        GifFile->SColorMap = NULL;
296
883
    }
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
954
    return GIF_OK;
304
977
}
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
43.4k
{
323
43.4k
    GifByteType Buf;
324
43.4k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
325
326
43.4k
    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
43.4k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
334
68
        GifFile->Error = D_GIF_ERR_READ_FAILED;
335
68
        return GIF_ERROR;
336
68
    }
337
338
    //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
339
43.3k
    switch (Buf) {
340
40.0k
      case DESCRIPTOR_INTRODUCER:
341
40.0k
          *Type = IMAGE_DESC_RECORD_TYPE;
342
40.0k
          break;
343
3.19k
      case EXTENSION_INTRODUCER:
344
3.19k
          *Type = EXTENSION_RECORD_TYPE;
345
3.19k
          break;
346
114
      case TERMINATOR_INTRODUCER:
347
114
          *Type = TERMINATE_RECORD_TYPE;
348
114
          break;
349
11
      default:
350
11
          *Type = UNDEFINED_RECORD_TYPE;
351
11
          GifFile->Error = D_GIF_ERR_WRONG_RECORD;
352
11
          return GIF_ERROR;
353
43.3k
    }
354
355
43.3k
    return GIF_OK;
356
43.3k
}
357
358
int
359
DGifGetImageHeader(GifFileType *GifFile)
360
40.0k
{
361
40.0k
    unsigned int BitsPerPixel;
362
40.0k
    GifByteType Buf[3];
363
40.0k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
364
365
40.0k
    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
40.0k
    if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
372
40.0k
        DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
373
40.0k
        DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
374
40.0k
        DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
375
36
        return GIF_ERROR;
376
39.9k
    if (InternalRead(GifFile, Buf, 1) != 1) {
377
10
        GifFile->Error = D_GIF_ERR_READ_FAILED;
378
10
        GifFreeMapObject(GifFile->Image.ColorMap);
379
10
        GifFile->Image.ColorMap = NULL;
380
10
        return GIF_ERROR;
381
10
    }
382
39.9k
    BitsPerPixel = (Buf[0] & 0x07) + 1;
383
39.9k
    GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
384
385
    /* Setup the colormap */
386
39.9k
    if (GifFile->Image.ColorMap) {
387
900
        GifFreeMapObject(GifFile->Image.ColorMap);
388
900
        GifFile->Image.ColorMap = NULL;
389
900
    }
390
    /* Does this image have local color map? */
391
39.9k
    if (Buf[0] & 0x80) {
392
961
        unsigned int i;
393
394
961
        GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
395
961
        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
3.94k
        for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
402
            /* coverity[check_return] */
403
3.02k
            if (InternalRead(GifFile, Buf, 3) != 3) {
404
41
                GifFreeMapObject(GifFile->Image.ColorMap);
405
41
                GifFile->Error = D_GIF_ERR_READ_FAILED;
406
41
                GifFile->Image.ColorMap = NULL;
407
41
                return GIF_ERROR;
408
41
            }
409
2.98k
            GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
410
2.98k
            GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
411
2.98k
            GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
412
2.98k
        }
413
961
    }
414
415
39.9k
    Private->PixelCount = (long)GifFile->Image.Width *
416
39.9k
       (long)GifFile->Image.Height;
417
418
    /* Reset decompress algorithm parameters. */
419
39.9k
    return DGifSetupDecompress(GifFile);
420
39.9k
}
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
40.0k
{
429
40.0k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
430
40.0k
    SavedImage *sp;
431
432
40.0k
    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
40.0k
    if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
439
117
        return GIF_ERROR;
440
117
    }
441
442
39.9k
    if (GifFile->SavedImages) {
443
39.1k
        SavedImage* new_saved_images =
444
39.1k
            (SavedImage *)reallocarray(GifFile->SavedImages,
445
39.1k
                            (GifFile->ImageCount + 1), sizeof(SavedImage));
446
39.1k
        if (new_saved_images == NULL) {
447
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
448
0
            return GIF_ERROR;
449
0
        }
450
39.1k
        GifFile->SavedImages = new_saved_images;
451
39.1k
    } else {
452
781
        if ((GifFile->SavedImages =
453
781
             (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
454
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
455
0
            return GIF_ERROR;
456
0
        }
457
781
    }
458
459
39.9k
    sp = &GifFile->SavedImages[GifFile->ImageCount];
460
39.9k
    memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
461
39.9k
    if (GifFile->Image.ColorMap != NULL) {
462
911
        sp->ImageDesc.ColorMap = GifMakeMapObject(
463
911
                                 GifFile->Image.ColorMap->ColorCount,
464
911
                                 GifFile->Image.ColorMap->Colors);
465
911
        if (sp->ImageDesc.ColorMap == NULL) {
466
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
467
0
            return GIF_ERROR;
468
0
        }
469
911
    }
470
39.9k
    sp->RasterBits = (unsigned char *)NULL;
471
39.9k
    sp->ExtensionBlockCount = 0;
472
39.9k
    sp->ExtensionBlocks = (ExtensionBlock *) NULL;
473
474
39.9k
    GifFile->ImageCount++;
475
476
39.9k
    return GIF_OK;
477
39.9k
}
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
49.2k
{
485
49.2k
    GifByteType *Dummy;
486
49.2k
    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
487
488
49.2k
    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
49.2k
    if (!LineLen)
495
0
        LineLen = GifFile->Image.Width;
496
497
49.2k
    if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498
0
        GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
499
0
        return GIF_ERROR;
500
0
    }
501
502
49.2k
    if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503
48.7k
        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
39.4k
            do
510
40.1k
                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
511
37
                    return GIF_ERROR;
512
40.1k
            while (Dummy != NULL) ;
513
39.4k
        }
514
48.7k
        return GIF_OK;
515
48.7k
    } else
516
480
        return GIF_ERROR;
517
49.2k
}
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.19k
{
566
3.19k
    GifByteType Buf;
567
3.19k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
568
569
    //fprintf(stderr, "### -> DGifGetExtension:\n");
570
3.19k
    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.19k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
578
8
        GifFile->Error = D_GIF_ERR_READ_FAILED;
579
8
        return GIF_ERROR;
580
8
    }
581
3.18k
    *ExtCode = Buf;
582
    //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
583
584
3.18k
    return DGifGetExtensionNext(GifFile, Extension);
585
3.19k
}
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
79.2k
{
595
79.2k
    GifByteType Buf;
596
79.2k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
597
598
    //fprintf(stderr, "### -> DGifGetExtensionNext\n");
599
79.2k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
600
56
        GifFile->Error = D_GIF_ERR_READ_FAILED;
601
56
        return GIF_ERROR;
602
56
    }
603
    //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
604
605
79.1k
    if (Buf > 0) {
606
75.0k
        *Extension = Private->Buf;    /* Use private unused buffer. */
607
75.0k
        (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
608
  /* coverity[tainted_data,check_return] */
609
75.0k
        if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
610
37
            GifFile->Error = D_GIF_ERR_READ_FAILED;
611
37
            return GIF_ERROR;
612
37
        }
613
75.0k
    } else
614
4.08k
        *Extension = NULL;
615
    //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
616
617
79.1k
    return GIF_OK;
618
79.1k
}
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
706
{
628
706
    if (GifExtensionLength != 4) {
629
214
  return GIF_ERROR;
630
214
    }
631
632
492
    GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
633
492
    GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
634
492
    GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
635
492
    if (GifExtension[0] & 0x01)
636
247
  GCB->TransparentColor = (int)GifExtension[3];
637
245
    else
638
245
  GCB->TransparentColor = NO_TRANSPARENT_COLOR;
639
640
492
    return GIF_OK;
641
706
}
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.1k
{
650
34.1k
    int i;
651
652
34.1k
    if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
653
0
  return GIF_ERROR;
654
655
34.1k
    GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
656
34.1k
    GCB->UserInputFlag = false;
657
34.1k
    GCB->DelayTime = 0;
658
34.1k
    GCB->TransparentColor = NO_TRANSPARENT_COLOR;
659
660
97.5k
    for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
661
64.1k
  ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
662
64.1k
  if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
663
706
      return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
664
64.1k
    }
665
666
33.4k
    return GIF_ERROR;
667
34.1k
}
668
669
/******************************************************************************
670
 This routine should be called last, to close the GIF file.
671
******************************************************************************/
672
int
673
DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
674
954
{
675
954
    GifFilePrivateType *Private;
676
677
954
    if (GifFile == NULL || GifFile->Private == NULL)
678
0
        return GIF_ERROR;
679
680
954
    if (GifFile->Image.ColorMap) {
681
20
        GifFreeMapObject(GifFile->Image.ColorMap);
682
20
        GifFile->Image.ColorMap = NULL;
683
20
    }
684
685
954
    if (GifFile->SColorMap) {
686
71
        GifFreeMapObject(GifFile->SColorMap);
687
71
        GifFile->SColorMap = NULL;
688
71
    }
689
690
954
    if (GifFile->SavedImages) {
691
781
        GifFreeSavedImages(GifFile);
692
781
        GifFile->SavedImages = NULL;
693
781
    }
694
695
954
    GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
696
697
954
    Private = (GifFilePrivateType *) GifFile->Private;
698
699
954
    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
954
    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
954
    free((char *)GifFile->Private);
717
954
    free(GifFile);
718
954
    if (ErrorCode != NULL)
719
954
  *ErrorCode = D_GIF_SUCCEEDED;
720
954
    return GIF_OK;
721
954
}
722
723
/******************************************************************************
724
 Get 2 bytes (word) from the given file:
725
******************************************************************************/
726
static int
727
DGifGetWord(GifFileType *GifFile, GifWord *Word)
728
162k
{
729
162k
    unsigned char c[2];
730
731
    /* coverity[check_return] */
732
162k
    if (InternalRead(GifFile, c, 2) != 2) {
733
40
        GifFile->Error = D_GIF_ERR_READ_FAILED;
734
40
        return GIF_ERROR;
735
40
    }
736
737
161k
    *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
738
161k
    return GIF_OK;
739
162k
}
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
40.1k
{
772
40.1k
    GifByteType Buf;
773
40.1k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
774
775
    /* coverity[tainted_data_argument] */
776
    /* coverity[check_return] */
777
40.1k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
778
21
        GifFile->Error = D_GIF_ERR_READ_FAILED;
779
21
        return GIF_ERROR;
780
21
    }
781
782
    /* coverity[lower_bounds] */
783
40.1k
    if (Buf > 0) {
784
775
        *CodeBlock = Private->Buf;    /* Use private unused buffer. */
785
775
        (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
786
  /* coverity[tainted_data] */
787
775
        if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
788
16
            GifFile->Error = D_GIF_ERR_READ_FAILED;
789
16
            return GIF_ERROR;
790
16
        }
791
39.3k
    } else {
792
39.3k
        *CodeBlock = NULL;
793
39.3k
        Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
794
39.3k
        Private->PixelCount = 0;    /* And local info. indicate image read. */
795
39.3k
    }
796
797
40.1k
    return GIF_OK;
798
40.1k
}
799
800
/******************************************************************************
801
 Setup the LZ decompression for this image:
802
******************************************************************************/
803
static int
804
DGifSetupDecompress(GifFileType *GifFile)
805
39.9k
{
806
39.9k
    int i, BitsPerPixel;
807
39.9k
    GifByteType CodeSize;
808
39.9k
    GifPrefixType *Prefix;
809
39.9k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
810
811
    /* coverity[check_return] */
812
39.9k
    if (InternalRead(GifFile, &CodeSize, 1) < 1) {    /* Read Code size from file. */
813
23
  return GIF_ERROR;    /* Failed to read Code size. */
814
23
    }
815
39.9k
    BitsPerPixel = CodeSize;
816
817
    /* this can only happen on a severely malformed GIF */
818
39.9k
    if (BitsPerPixel > 8) {
819
7
  GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
820
7
  return GIF_ERROR;    /* Failed to read Code size. */
821
7
    }
822
823
39.9k
    Private->Buf[0] = 0;    /* Input Buffer empty. */
824
39.9k
    Private->BitsPerPixel = BitsPerPixel;
825
39.9k
    Private->ClearCode = (1 << BitsPerPixel);
826
39.9k
    Private->EOFCode = Private->ClearCode + 1;
827
39.9k
    Private->RunningCode = Private->EOFCode + 1;
828
39.9k
    Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
829
39.9k
    Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
830
39.9k
    Private->StackPtr = 0;    /* No pixels on the pixel stack. */
831
39.9k
    Private->LastCode = NO_SUCH_CODE;
832
39.9k
    Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
833
39.9k
    Private->CrntShiftDWord = 0;
834
835
39.9k
    Prefix = Private->Prefix;
836
163M
    for (i = 0; i <= LZ_MAX_CODE; i++)
837
163M
        Prefix[i] = NO_SUCH_CODE;
838
839
39.9k
    return GIF_OK;
840
39.9k
}
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
49.2k
{
851
49.2k
    int i = 0;
852
49.2k
    int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
853
49.2k
    GifByteType *Stack, *Suffix;
854
49.2k
    GifPrefixType *Prefix;
855
49.2k
    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
856
857
49.2k
    StackPtr = Private->StackPtr;
858
49.2k
    Prefix = Private->Prefix;
859
49.2k
    Suffix = Private->Suffix;
860
49.2k
    Stack = Private->Stack;
861
49.2k
    EOFCode = Private->EOFCode;
862
49.2k
    ClearCode = Private->ClearCode;
863
49.2k
    LastCode = Private->LastCode;
864
865
49.2k
    if (StackPtr > LZ_MAX_CODE) {
866
0
        return GIF_ERROR;
867
0
    }
868
869
49.2k
    if (StackPtr != 0) {
870
        /* Let pop the stack off before continueing to read the GIF file: */
871
37.4k
        while (StackPtr != 0 && i < LineLen)
872
31.6k
            Line[i++] = Stack[--StackPtr];
873
5.78k
    }
874
875
710k
    while (i < LineLen) {    /* Decode LineLen items. */
876
661k
        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
877
393
            return GIF_ERROR;
878
879
660k
        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
6
      GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
884
6
      return GIF_ERROR;
885
660k
        } else if (CrntCode == ClearCode) {
886
            /* We need to start over again: */
887
302M
            for (j = 0; j <= LZ_MAX_CODE; j++)
888
302M
                Prefix[j] = NO_SUCH_CODE;
889
73.8k
            Private->RunningCode = Private->EOFCode + 1;
890
73.8k
            Private->RunningBits = Private->BitsPerPixel + 1;
891
73.8k
            Private->MaxCode1 = 1 << Private->RunningBits;
892
73.8k
            LastCode = Private->LastCode = NO_SUCH_CODE;
893
587k
        } 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
587k
            if (CrntCode < ClearCode) {
898
                /* This is simple - its pixel scalar, so add it to output: */
899
288k
                Line[i++] = CrntCode;
900
298k
            } 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
298k
                if (Prefix[CrntCode] == NO_SUCH_CODE) {
906
63.4k
                    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
63.4k
                    if (CrntCode == Private->RunningCode - 2) {
913
22.9k
                        Suffix[Private->RunningCode - 2] =
914
22.9k
                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
915
22.9k
                                                                 LastCode,
916
22.9k
                                                                 ClearCode);
917
40.5k
                    } else {
918
40.5k
                        Suffix[Private->RunningCode - 2] =
919
40.5k
                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
920
40.5k
                                                                 CrntCode,
921
40.5k
                                                                 ClearCode);
922
40.5k
                    }
923
63.4k
                } else
924
235k
                    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.35M
                while (StackPtr < LZ_MAX_CODE &&
931
1.35M
                       CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
932
1.05M
                    Stack[StackPtr++] = Suffix[CrntPrefix];
933
1.05M
                    CrntPrefix = Prefix[CrntPrefix];
934
1.05M
                }
935
298k
                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
936
81
                    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
937
81
                    return GIF_ERROR;
938
81
                }
939
                /* Push the last character on stack: */
940
298k
                Stack[StackPtr++] = CrntPrefix;
941
942
                /* Now lets pop all the stack into output: */
943
1.67M
                while (StackPtr != 0 && i < LineLen)
944
1.37M
                    Line[i++] = Stack[--StackPtr];
945
298k
            }
946
586k
            if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
947
512k
                Prefix[Private->RunningCode - 2] = LastCode;
948
949
512k
                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
22.8k
                    Suffix[Private->RunningCode - 2] =
955
22.8k
                       DGifGetPrefixChar(Prefix, LastCode, ClearCode);
956
489k
                } else {
957
489k
                    Suffix[Private->RunningCode - 2] =
958
489k
                       DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
959
489k
                }
960
512k
            }
961
586k
            LastCode = CrntCode;
962
586k
        }
963
660k
    }
964
965
48.7k
    Private->LastCode = LastCode;
966
48.7k
    Private->StackPtr = StackPtr;
967
968
48.7k
    return GIF_OK;
969
49.2k
}
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
575k
{
980
575k
    int i = 0;
981
982
1.94M
    while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
983
1.45M
        if (Code > LZ_MAX_CODE) {
984
81.0k
            return NO_SUCH_CODE;
985
81.0k
        }
986
1.37M
        Code = Prefix[Code];
987
1.37M
    }
988
494k
    return Code;
989
575k
}
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
661k
{
1037
661k
    static const unsigned short CodeMasks[] = {
1038
661k
  0x0000, 0x0001, 0x0003, 0x0007,
1039
661k
  0x000f, 0x001f, 0x003f, 0x007f,
1040
661k
  0x00ff, 0x01ff, 0x03ff, 0x07ff,
1041
661k
  0x0fff
1042
661k
    };
1043
1044
661k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1045
1046
661k
    GifByteType NextByte;
1047
1048
    /* The image can't contain more than LZ_BITS per code. */
1049
661k
    if (Private->RunningBits > LZ_BITS) {
1050
0
        GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1051
0
        return GIF_ERROR;
1052
0
    }
1053
    
1054
1.39M
    while (Private->CrntShiftState < Private->RunningBits) {
1055
        /* Needs to get more bytes from input stream for next code: */
1056
733k
        if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
1057
393
            return GIF_ERROR;
1058
393
        }
1059
733k
        Private->CrntShiftDWord |=
1060
733k
      ((unsigned long)NextByte) << Private->CrntShiftState;
1061
733k
        Private->CrntShiftState += 8;
1062
733k
    }
1063
660k
    *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1064
1065
660k
    Private->CrntShiftDWord >>= Private->RunningBits;
1066
660k
    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
660k
    if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1074
660k
  ++Private->RunningCode > Private->MaxCode1 &&
1075
660k
  Private->RunningBits < LZ_BITS) {
1076
155k
        Private->MaxCode1 <<= 1;
1077
155k
        Private->RunningBits++;
1078
155k
    }
1079
660k
    return GIF_OK;
1080
661k
}
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
733k
{
1091
733k
    if (Buf[0] == 0) {
1092
        /* Needs to read the next buffer - this one is empty: */
1093
  /* coverity[check_return] */
1094
43.5k
        if (InternalRead(GifFile, Buf, 1) != 1) {
1095
368
            GifFile->Error = D_GIF_ERR_READ_FAILED;
1096
368
            return GIF_ERROR;
1097
368
        }
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
43.1k
        if (Buf[0] == 0) {
1103
4
            GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1104
4
            return GIF_ERROR;
1105
4
        }
1106
43.1k
        if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1107
21
            GifFile->Error = D_GIF_ERR_READ_FAILED;
1108
21
            return GIF_ERROR;
1109
21
        }
1110
43.1k
        *NextByte = Buf[1];
1111
43.1k
        Buf[1] = 2;    /* We use now the second place as last char read! */
1112
43.1k
        Buf[0]--;
1113
690k
    } else {
1114
690k
        *NextByte = Buf[Buf[1]++];
1115
690k
        Buf[0]--;
1116
690k
    }
1117
1118
733k
    return GIF_OK;
1119
733k
}
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
954
{
1129
954
    size_t ImageSize;
1130
954
    GifRecordType RecordType;
1131
954
    SavedImage *sp;
1132
954
    GifByteType *ExtData;
1133
954
    int ExtFunction;
1134
1135
954
    GifFile->ExtensionBlocks = NULL;
1136
954
    GifFile->ExtensionBlockCount = 0;
1137
1138
43.4k
    do {
1139
43.4k
        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1140
79
            return (GIF_ERROR);
1141
1142
43.3k
        switch (RecordType) {
1143
40.0k
          case IMAGE_DESC_RECORD_TYPE:
1144
40.0k
              if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1145
117
                  return (GIF_ERROR);
1146
1147
39.9k
              sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1148
              /* Allocate memory for the image */
1149
39.9k
              if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
1150
39.9k
                      sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1151
26
                  return GIF_ERROR;
1152
26
              }
1153
39.8k
              ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1154
1155
39.8k
              if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1156
0
                  return GIF_ERROR;
1157
0
              }
1158
39.8k
              sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
1159
39.8k
                      sizeof(GifPixelType));
1160
1161
39.8k
              if (sp->RasterBits == NULL) {
1162
0
                  return GIF_ERROR;
1163
0
              }
1164
1165
39.8k
        if (sp->ImageDesc.Interlace) {
1166
37.8k
      int i, j;
1167
       /* 
1168
        * The way an interlaced image should be read - 
1169
        * offsets and jumps...
1170
        */
1171
37.8k
      int InterlacedOffset[] = { 0, 4, 2, 1 };
1172
37.8k
      int InterlacedJumps[] = { 8, 8, 4, 2 };
1173
      /* Need to perform 4 passes on the image */
1174
188k
      for (i = 0; i < 4; i++)
1175
150k
          for (j = InterlacedOffset[i]; 
1176
197k
         j < sp->ImageDesc.Height;
1177
150k
         j += InterlacedJumps[i]) {
1178
47.2k
        if (DGifGetLine(GifFile, 
1179
47.2k
            sp->RasterBits+j*sp->ImageDesc.Width, 
1180
47.2k
            sp->ImageDesc.Width) == GIF_ERROR)
1181
250
            return GIF_ERROR;
1182
47.2k
          }
1183
37.8k
        }
1184
2.04k
        else {
1185
2.04k
      if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1186
267
          return (GIF_ERROR);
1187
2.04k
        }
1188
1189
39.3k
              if (GifFile->ExtensionBlocks) {
1190
1.69k
                  sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1191
1.69k
                  sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1192
1193
1.69k
                  GifFile->ExtensionBlocks = NULL;
1194
1.69k
                  GifFile->ExtensionBlockCount = 0;
1195
1.69k
              }
1196
39.3k
              break;
1197
1198
3.19k
          case EXTENSION_RECORD_TYPE:
1199
3.19k
              if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1200
35
                  return (GIF_ERROR);
1201
        /* Create an extension block with our data */
1202
3.15k
              if (ExtData != NULL) {
1203
2.16k
      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1204
2.16k
             &GifFile->ExtensionBlocks, 
1205
2.16k
             ExtFunction, ExtData[0], &ExtData[1])
1206
2.16k
          == GIF_ERROR)
1207
0
          return (GIF_ERROR);
1208
2.16k
        }
1209
76.0k
              for (;;) {
1210
76.0k
                  if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1211
66
                      return (GIF_ERROR);
1212
75.9k
      if (ExtData == NULL)
1213
3.09k
          break;
1214
                  /* Continue the extension block */
1215
72.8k
      if (ExtData != NULL)
1216
72.8k
          if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1217
72.8k
                 &GifFile->ExtensionBlocks,
1218
72.8k
                 CONTINUE_EXT_FUNC_CODE, 
1219
72.8k
                 ExtData[0], &ExtData[1]) == GIF_ERROR)
1220
0
                      return (GIF_ERROR);
1221
72.8k
              }
1222
3.09k
              break;
1223
1224
3.09k
          case TERMINATE_RECORD_TYPE:
1225
114
              break;
1226
1227
0
          default:    /* Should be trapped by DGifGetRecordType */
1228
0
              break;
1229
43.3k
        }
1230
43.3k
    } while (RecordType != TERMINATE_RECORD_TYPE);
1231
1232
    /* Sanity check for corrupted file */
1233
114
    if (GifFile->ImageCount == 0) {
1234
1
  GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1235
1
  return(GIF_ERROR);
1236
1
    }
1237
1238
113
    return (GIF_OK);
1239
114
}
1240
1241
/* end */