Coverage Report

Created: 2026-05-16 06:09

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