Coverage Report

Created: 2026-11-12 06:28

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