Coverage Report

Created: 2023-12-08 06:35

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