Coverage Report

Created: 2025-10-30 07:08

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