Coverage Report

Created: 2025-06-24 07:08

/src/giflib-code/dgif_lib.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
3
dgif_lib.c - GIF decoding
4
5
The functions here and in egif_lib.c are partitioned carefully so that
6
if you only require one of read and write capability, only one of these
7
two modules will be linked.  Preserve this property!
8
9
*****************************************************************************/
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
329k
#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
31
32
/* avoid extra function call in case we use fread (TVT) */
33
1.07M
static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34
  // fprintf(stderr, "### Read: %d\n", len);
35
1.07M
  return (((GifFilePrivateType *)gif->Private)->Read
36
1.07M
              ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len)
37
1.07M
              : fread(buf, 1, len,
38
0
                      ((GifFilePrivateType *)gif->Private)->File));
39
1.07M
}
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.95k
GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) {
168
1.95k
  char Buf[GIF_STAMP_LEN + 1];
169
1.95k
  GifFileType *GifFile;
170
1.95k
  GifFilePrivateType *Private;
171
172
1.95k
  GifFile = (GifFileType *)malloc(sizeof(GifFileType));
173
1.95k
  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.95k
  memset(GifFile, '\0', sizeof(GifFileType));
181
182
  /* Belt and suspenders, in case the null pointer isn't zero */
183
1.95k
  GifFile->SavedImages = NULL;
184
1.95k
  GifFile->SColorMap = NULL;
185
186
1.95k
  Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
187
1.95k
  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.95k
  /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
195
196
1.95k
  GifFile->Private = (void *)Private;
197
1.95k
  Private->FileHandle = 0;
198
1.95k
  Private->File = NULL;
199
1.95k
  Private->FileState = FILE_STATE_READ;
200
201
1.95k
  Private->Read = readFunc;     /* TVT */
202
1.95k
  GifFile->UserData = userData; /* TVT */
203
204
  /* Lets see if this is a GIF file: */
205
  /* coverity[check_return] */
206
1.95k
  if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
207
1.95k
      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.94k
  Buf[GIF_STAMP_LEN] = '\0';
218
1.94k
  if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
219
37
    if (Error != NULL) {
220
37
      *Error = D_GIF_ERR_NOT_GIF_FILE;
221
37
    }
222
37
    free((char *)Private);
223
37
    free((char *)GifFile);
224
37
    return NULL;
225
37
  }
226
227
1.91k
  if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
228
48
    free((char *)Private);
229
48
    free((char *)GifFile);
230
48
    if (Error != NULL) {
231
48
      *Error = D_GIF_ERR_NO_SCRN_DSCR;
232
48
    }
233
48
    return NULL;
234
48
  }
235
236
1.86k
  GifFile->Error = 0;
237
238
  /* What version of GIF? */
239
1.86k
  Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
240
241
1.86k
  return GifFile;
242
1.91k
}
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.91k
int DGifGetScreenDesc(GifFileType *GifFile) {
249
1.91k
  int BitsPerPixel;
250
1.91k
  bool SortFlag;
251
1.91k
  GifByteType Buf[3];
252
1.91k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
253
254
1.91k
  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.91k
  if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
262
1.91k
      DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) {
263
4
    return GIF_ERROR;
264
4
  }
265
266
1.90k
  if (InternalRead(GifFile, Buf, 3) != 3) {
267
5
    GifFile->Error = D_GIF_ERR_READ_FAILED;
268
5
    GifFreeMapObject(GifFile->SColorMap);
269
5
    GifFile->SColorMap = NULL;
270
5
    return GIF_ERROR;
271
5
  }
272
1.90k
  GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
273
1.90k
  SortFlag = (Buf[0] & 0x08) != 0;
274
1.90k
  BitsPerPixel = (Buf[0] & 0x07) + 1;
275
1.90k
  GifFile->SBackGroundColor = Buf[1];
276
1.90k
  GifFile->AspectByte = Buf[2];
277
1.90k
  if (Buf[0] & 0x80) { /* Do we have global color map? */
278
138
    int i;
279
280
138
    GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
281
138
    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
138
    GifFile->SColorMap->SortFlag = SortFlag;
288
1.43k
    for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
289
      /* coverity[check_return] */
290
1.33k
      if (InternalRead(GifFile, Buf, 3) != 3) {
291
39
        GifFreeMapObject(GifFile->SColorMap);
292
39
        GifFile->SColorMap = NULL;
293
39
        GifFile->Error = D_GIF_ERR_READ_FAILED;
294
39
        return GIF_ERROR;
295
39
      }
296
1.29k
      GifFile->SColorMap->Colors[i].Red = Buf[0];
297
1.29k
      GifFile->SColorMap->Colors[i].Green = Buf[1];
298
1.29k
      GifFile->SColorMap->Colors[i].Blue = Buf[2];
299
1.29k
    }
300
1.76k
  } else {
301
1.76k
    GifFile->SColorMap = NULL;
302
1.76k
  }
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.86k
  return GIF_OK;
310
1.90k
}
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
96.7k
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) {
326
96.7k
  GifByteType Buf;
327
96.7k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
328
329
96.7k
  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
96.7k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
337
87
    GifFile->Error = D_GIF_ERR_READ_FAILED;
338
87
    return GIF_ERROR;
339
87
  }
340
341
  // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
342
96.6k
  switch (Buf) {
343
78.8k
  case DESCRIPTOR_INTRODUCER:
344
78.8k
    *Type = IMAGE_DESC_RECORD_TYPE;
345
78.8k
    break;
346
17.3k
  case EXTENSION_INTRODUCER:
347
17.3k
    *Type = EXTENSION_RECORD_TYPE;
348
17.3k
    break;
349
315
  case TERMINATOR_INTRODUCER:
350
315
    *Type = TERMINATE_RECORD_TYPE;
351
315
    break;
352
114
  default:
353
114
    *Type = UNDEFINED_RECORD_TYPE;
354
114
    GifFile->Error = D_GIF_ERR_WRONG_RECORD;
355
114
    return GIF_ERROR;
356
96.6k
  }
357
358
96.5k
  return GIF_OK;
359
96.6k
}
360
361
78.8k
int DGifGetImageHeader(GifFileType *GifFile) {
362
78.8k
  unsigned int BitsPerPixel;
363
78.8k
  GifByteType Buf[3];
364
78.8k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
365
366
78.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
78.8k
  if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
373
78.8k
      DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
374
78.8k
      DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
375
78.8k
      DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) {
376
44
    return GIF_ERROR;
377
44
  }
378
78.7k
  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
78.7k
  BitsPerPixel = (Buf[0] & 0x07) + 1;
385
78.7k
  GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
386
387
  /* Setup the colormap */
388
78.7k
  if (GifFile->Image.ColorMap) {
389
1.43k
    GifFreeMapObject(GifFile->Image.ColorMap);
390
1.43k
    GifFile->Image.ColorMap = NULL;
391
1.43k
  }
392
  /* Does this image have local color map? */
393
78.7k
  if (Buf[0] & 0x80) {
394
1.56k
    unsigned int i;
395
396
1.56k
    GifFile->Image.ColorMap =
397
1.56k
        GifMakeMapObject(1 << BitsPerPixel, NULL);
398
1.56k
    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.63k
    for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
405
      /* coverity[check_return] */
406
5.13k
      if (InternalRead(GifFile, Buf, 3) != 3) {
407
61
        GifFreeMapObject(GifFile->Image.ColorMap);
408
61
        GifFile->Error = D_GIF_ERR_READ_FAILED;
409
61
        GifFile->Image.ColorMap = NULL;
410
61
        return GIF_ERROR;
411
61
      }
412
5.07k
      GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
413
5.07k
      GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
414
5.07k
      GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
415
5.07k
    }
416
1.56k
  }
417
418
78.6k
  Private->PixelCount =
419
78.6k
      (long)GifFile->Image.Width * (long)GifFile->Image.Height;
420
421
  /* Reset decompress algorithm parameters. */
422
78.6k
  return DGifSetupDecompress(GifFile);
423
78.7k
}
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
78.8k
int DGifGetImageDesc(GifFileType *GifFile) {
430
78.8k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
431
78.8k
  SavedImage *sp;
432
433
78.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
78.8k
  if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
440
199
    return GIF_ERROR;
441
199
  }
442
443
78.6k
  if (GifFile->SavedImages) {
444
77.2k
    SavedImage *new_saved_images = (SavedImage *)reallocarray(
445
77.2k
        GifFile->SavedImages, (GifFile->ImageCount + 1),
446
77.2k
        sizeof(SavedImage));
447
77.2k
    if (new_saved_images == NULL) {
448
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
449
0
      return GIF_ERROR;
450
0
    }
451
77.2k
    GifFile->SavedImages = new_saved_images;
452
77.2k
  } else {
453
1.31k
    if ((GifFile->SavedImages =
454
1.31k
             (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
455
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
456
0
      return GIF_ERROR;
457
0
    }
458
1.31k
  }
459
460
78.6k
  sp = &GifFile->SavedImages[GifFile->ImageCount];
461
78.6k
  memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
462
78.6k
  if (GifFile->Image.ColorMap != NULL) {
463
1.47k
    sp->ImageDesc.ColorMap =
464
1.47k
        GifMakeMapObject(GifFile->Image.ColorMap->ColorCount,
465
1.47k
                         GifFile->Image.ColorMap->Colors);
466
1.47k
    if (sp->ImageDesc.ColorMap == NULL) {
467
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
468
0
      return GIF_ERROR;
469
0
    }
470
1.47k
  }
471
78.6k
  sp->RasterBits = (unsigned char *)NULL;
472
78.6k
  sp->ExtensionBlockCount = 0;
473
78.6k
  sp->ExtensionBlocks = (ExtensionBlock *)NULL;
474
475
78.6k
  GifFile->ImageCount++;
476
477
78.6k
  return GIF_OK;
478
78.6k
}
479
480
/******************************************************************************
481
 Get one full scanned line (Line) of length LineLen from GIF file.
482
******************************************************************************/
483
752k
int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) {
484
752k
  GifByteType *Dummy;
485
752k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
486
487
752k
  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
752k
  if (!LineLen) {
494
0
    LineLen = GifFile->Image.Width;
495
0
  }
496
497
752k
  if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498
0
    GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
499
0
    return GIF_ERROR;
500
0
  }
501
502
752k
  if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503
751k
    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
82.8k
      do {
510
82.8k
        if (DGifGetCodeNext(GifFile, &Dummy) ==
511
82.8k
            GIF_ERROR) {
512
52
          return GIF_ERROR;
513
52
        }
514
82.8k
      } while (Dummy != NULL);
515
77.7k
    }
516
751k
    return GIF_OK;
517
751k
  } else {
518
771
    return GIF_ERROR;
519
771
  }
520
752k
}
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
17.3k
                     GifByteType **Extension) {
568
17.3k
  GifByteType Buf;
569
17.3k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
570
571
  // fprintf(stderr, "### -> DGifGetExtension:\n");
572
17.3k
  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
17.3k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
580
6
    GifFile->Error = D_GIF_ERR_READ_FAILED;
581
6
    return GIF_ERROR;
582
6
  }
583
17.3k
  *ExtCode = Buf;
584
  // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call
585
  // next\n", Buf);
586
587
17.3k
  return DGifGetExtensionNext(GifFile, Extension);
588
17.3k
}
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
116k
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) {
596
116k
  GifByteType Buf;
597
116k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
598
599
  // fprintf(stderr, "### -> DGifGetExtensionNext\n");
600
116k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
601
65
    GifFile->Error = D_GIF_ERR_READ_FAILED;
602
65
    return GIF_ERROR;
603
65
  }
604
  // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
605
606
116k
  if (Buf > 0) {
607
97.0k
    *Extension = Private->Buf; /* Use private unused buffer. */
608
97.0k
    (*Extension)[0] =
609
97.0k
        Buf; /* Pascal strings notation (pos. 0 is len.). */
610
             /* coverity[tainted_data,check_return] */
611
97.0k
    if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
612
149
      GifFile->Error = D_GIF_ERR_READ_FAILED;
613
149
      return GIF_ERROR;
614
149
    }
615
97.0k
  } else {
616
19.3k
    *Extension = NULL;
617
19.3k
  }
618
  // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
619
620
116k
  return GIF_OK;
621
116k
}
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
10.8k
                       GraphicsControlBlock *GCB) {
630
10.8k
  if (GifExtensionLength != 4) {
631
705
    return GIF_ERROR;
632
705
  }
633
634
10.1k
  GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
635
10.1k
  GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
636
10.1k
  GCB->DelayTime =
637
10.1k
      UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
638
10.1k
  if (GifExtension[0] & 0x01) {
639
928
    GCB->TransparentColor = (int)GifExtension[3];
640
9.21k
  } else {
641
9.21k
    GCB->TransparentColor = NO_TRANSPARENT_COLOR;
642
9.21k
  }
643
644
10.1k
  return GIF_OK;
645
10.8k
}
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
69.3k
                            GraphicsControlBlock *GCB) {
653
69.3k
  int i;
654
655
69.3k
  if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) {
656
0
    return GIF_ERROR;
657
0
  }
658
659
69.3k
  GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
660
69.3k
  GCB->UserInputFlag = false;
661
69.3k
  GCB->DelayTime = 0;
662
69.3k
  GCB->TransparentColor = NO_TRANSPARENT_COLOR;
663
664
123k
  for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount;
665
69.3k
       i++) {
666
64.5k
    ExtensionBlock *ep =
667
64.5k
        &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
668
64.5k
    if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
669
10.8k
      return DGifExtensionToGCB(ep->ByteCount, ep->Bytes,
670
10.8k
                                GCB);
671
10.8k
    }
672
64.5k
  }
673
674
58.5k
  return GIF_ERROR;
675
69.3k
}
676
677
/******************************************************************************
678
 This routine should be called last, to close the GIF file.
679
******************************************************************************/
680
1.86k
int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) {
681
1.86k
  GifFilePrivateType *Private;
682
683
1.86k
  if (GifFile == NULL || GifFile->Private == NULL) {
684
0
    return GIF_ERROR;
685
0
  }
686
687
1.86k
  if (GifFile->Image.ColorMap) {
688
61
    GifFreeMapObject(GifFile->Image.ColorMap);
689
61
    GifFile->Image.ColorMap = NULL;
690
61
  }
691
692
1.86k
  if (GifFile->SColorMap) {
693
99
    GifFreeMapObject(GifFile->SColorMap);
694
99
    GifFile->SColorMap = NULL;
695
99
  }
696
697
1.86k
  if (GifFile->SavedImages) {
698
1.31k
    GifFreeSavedImages(GifFile);
699
1.31k
    GifFile->SavedImages = NULL;
700
1.31k
  }
701
702
1.86k
  GifFreeExtensions(&GifFile->ExtensionBlockCount,
703
1.86k
                    &GifFile->ExtensionBlocks);
704
705
1.86k
  Private = (GifFilePrivateType *)GifFile->Private;
706
707
1.86k
  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.86k
  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.86k
  free((char *)GifFile->Private);
727
1.86k
  free(GifFile);
728
1.86k
  if (ErrorCode != NULL) {
729
1.86k
    *ErrorCode = D_GIF_SUCCEEDED;
730
1.86k
  }
731
1.86k
  return GIF_OK;
732
1.86k
}
733
734
/******************************************************************************
735
 Get 2 bytes (word) from the given file:
736
******************************************************************************/
737
318k
static int DGifGetWord(GifFileType *GifFile, GifWord *Word) {
738
318k
  unsigned char c[2];
739
740
  /* coverity[check_return] */
741
318k
  if (InternalRead(GifFile, c, 2) != 2) {
742
48
    GifFile->Error = D_GIF_ERR_READ_FAILED;
743
48
    return GIF_ERROR;
744
48
  }
745
746
318k
  *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
747
318k
  return GIF_OK;
748
318k
}
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
82.8k
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) {
777
82.8k
  GifByteType Buf;
778
82.8k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
779
780
  /* coverity[tainted_data_argument] */
781
  /* coverity[check_return] */
782
82.8k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
783
24
    GifFile->Error = D_GIF_ERR_READ_FAILED;
784
24
    return GIF_ERROR;
785
24
  }
786
787
  /* coverity[lower_bounds] */
788
82.8k
  if (Buf > 0) {
789
5.16k
    *CodeBlock = Private->Buf; /* Use private unused buffer. */
790
5.16k
    (*CodeBlock)[0] =
791
5.16k
        Buf; /* Pascal strings notation (pos. 0 is len.). */
792
             /* coverity[tainted_data] */
793
5.16k
    if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
794
28
      GifFile->Error = D_GIF_ERR_READ_FAILED;
795
28
      return GIF_ERROR;
796
28
    }
797
77.6k
  } else {
798
77.6k
    *CodeBlock = NULL;
799
77.6k
    Private->Buf[0] = 0; /* Make sure the buffer is empty! */
800
77.6k
    Private->PixelCount =
801
77.6k
        0; /* And local info. indicate image read. */
802
77.6k
  }
803
804
82.8k
  return GIF_OK;
805
82.8k
}
806
807
/******************************************************************************
808
 Setup the LZ decompression for this image:
809
******************************************************************************/
810
78.6k
static int DGifSetupDecompress(GifFileType *GifFile) {
811
78.6k
  int i, BitsPerPixel;
812
78.6k
  GifByteType CodeSize;
813
78.6k
  GifPrefixType *Prefix;
814
78.6k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
815
816
  /* coverity[check_return] */
817
78.6k
  if (InternalRead(GifFile, &CodeSize, 1) <
818
78.6k
      1) { /* Read Code size from file. */
819
35
    GifFile->Error = D_GIF_ERR_READ_FAILED;
820
35
    return GIF_ERROR; /* Failed to read Code size. */
821
35
  }
822
78.6k
  BitsPerPixel = CodeSize;
823
824
  /* this can only happen on a severely malformed GIF */
825
78.6k
  if (BitsPerPixel > 8) {
826
49
    GifFile->Error =
827
49
        D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
828
49
    return GIF_ERROR;          /* Failed to read Code size. */
829
49
  }
830
831
78.6k
  Private->Buf[0] = 0; /* Input Buffer empty. */
832
78.6k
  Private->BitsPerPixel = BitsPerPixel;
833
78.6k
  Private->ClearCode = (1 << BitsPerPixel);
834
78.6k
  Private->EOFCode = Private->ClearCode + 1;
835
78.6k
  Private->RunningCode = Private->EOFCode + 1;
836
78.6k
  Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
837
78.6k
  Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
838
78.6k
  Private->StackPtr = 0; /* No pixels on the pixel stack. */
839
78.6k
  Private->LastCode = NO_SUCH_CODE;
840
78.6k
  Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
841
78.6k
  Private->CrntShiftDWord = 0;
842
843
78.6k
  Prefix = Private->Prefix;
844
322M
  for (i = 0; i <= LZ_MAX_CODE; i++) {
845
321M
    Prefix[i] = NO_SUCH_CODE;
846
321M
  }
847
848
78.6k
  return GIF_OK;
849
78.6k
}
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
752k
                              int LineLen) {
859
752k
  int i = 0;
860
752k
  int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
861
752k
  GifByteType *Stack, *Suffix;
862
752k
  GifPrefixType *Prefix;
863
752k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
864
865
752k
  StackPtr = Private->StackPtr;
866
752k
  Prefix = Private->Prefix;
867
752k
  Suffix = Private->Suffix;
868
752k
  Stack = Private->Stack;
869
752k
  EOFCode = Private->EOFCode;
870
752k
  ClearCode = Private->ClearCode;
871
752k
  LastCode = Private->LastCode;
872
873
752k
  if (StackPtr > LZ_MAX_CODE) {
874
0
    return GIF_ERROR;
875
0
  }
876
877
752k
  if (StackPtr != 0) {
878
    /* Let pop the stack off before continueing to read the GIF
879
     * file: */
880
943k
    while (StackPtr != 0 && i < LineLen) {
881
511k
      Line[i++] = Stack[--StackPtr];
882
511k
    }
883
432k
  }
884
885
2.04M
  while (i < LineLen) { /* Decode LineLen items. */
886
1.29M
    if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) {
887
584
      return GIF_ERROR;
888
584
    }
889
890
1.29M
    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
28
      GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
896
28
      return GIF_ERROR;
897
1.29M
    } else if (CrntCode == ClearCode) {
898
      /* We need to start over again: */
899
850M
      for (j = 0; j <= LZ_MAX_CODE; j++) {
900
850M
        Prefix[j] = NO_SUCH_CODE;
901
850M
      }
902
207k
      Private->RunningCode = Private->EOFCode + 1;
903
207k
      Private->RunningBits = Private->BitsPerPixel + 1;
904
207k
      Private->MaxCode1 = 1 << Private->RunningBits;
905
207k
      LastCode = Private->LastCode = NO_SUCH_CODE;
906
1.08M
    } 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.08M
      if (CrntCode < ClearCode) {
911
        /* This is simple - its pixel scalar, so add it
912
         * to output: */
913
477k
        Line[i++] = CrntCode;
914
612k
      } 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
612k
        if (Prefix[CrntCode] == NO_SUCH_CODE) {
921
229k
          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
229k
          if (CrntCode ==
930
229k
              Private->RunningCode - 2) {
931
79.3k
            Suffix[Private->RunningCode -
932
79.3k
                   2] = Stack[StackPtr++] =
933
79.3k
                DGifGetPrefixChar(
934
79.3k
                    Prefix, LastCode,
935
79.3k
                    ClearCode);
936
149k
          } else {
937
149k
            Suffix[Private->RunningCode -
938
149k
                   2] = Stack[StackPtr++] =
939
149k
                DGifGetPrefixChar(
940
149k
                    Prefix, CrntCode,
941
149k
                    ClearCode);
942
149k
          }
943
383k
        } else {
944
383k
          CrntPrefix = CrntCode;
945
383k
        }
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.81M
        while (StackPtr < LZ_MAX_CODE &&
953
2.81M
               CrntPrefix > ClearCode &&
954
2.81M
               CrntPrefix <= LZ_MAX_CODE) {
955
2.20M
          Stack[StackPtr++] = Suffix[CrntPrefix];
956
2.20M
          CrntPrefix = Prefix[CrntPrefix];
957
2.20M
        }
958
612k
        if (StackPtr >= LZ_MAX_CODE ||
959
612k
            CrntPrefix > LZ_MAX_CODE) {
960
159
          GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
961
159
          return GIF_ERROR;
962
159
        }
963
        /* Push the last character on stack: */
964
612k
        Stack[StackPtr++] = CrntPrefix;
965
966
        /* Now lets pop all the stack into output: */
967
3.10M
        while (StackPtr != 0 && i < LineLen) {
968
2.48M
          Line[i++] = Stack[--StackPtr];
969
2.48M
        }
970
612k
      }
971
1.08M
      if (LastCode != NO_SUCH_CODE &&
972
1.08M
          Private->RunningCode - 2 < (LZ_MAX_CODE + 1) &&
973
1.08M
          Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
974
933k
        Prefix[Private->RunningCode - 2] = LastCode;
975
976
933k
        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
79.3k
          Suffix[Private->RunningCode - 2] =
984
79.3k
              DGifGetPrefixChar(Prefix, LastCode,
985
79.3k
                                ClearCode);
986
854k
        } else {
987
854k
          Suffix[Private->RunningCode - 2] =
988
854k
              DGifGetPrefixChar(Prefix, CrntCode,
989
854k
                                ClearCode);
990
854k
        }
991
933k
      }
992
1.08M
      LastCode = CrntCode;
993
1.08M
    }
994
1.29M
  }
995
996
751k
  Private->LastCode = LastCode;
997
751k
  Private->StackPtr = StackPtr;
998
999
751k
  return GIF_OK;
1000
752k
}
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.16M
                             int ClearCode) {
1010
1.16M
  int i = 0;
1011
1012
3.81M
  while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
1013
2.94M
    if (Code > LZ_MAX_CODE) {
1014
299k
      return NO_SUCH_CODE;
1015
299k
    }
1016
2.64M
    Code = Prefix[Code];
1017
2.64M
  }
1018
863k
  return Code;
1019
1.16M
}
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.29M
static int DGifDecompressInput(GifFileType *GifFile, int *Code) {
1066
1.29M
  static const unsigned short CodeMasks[] = {
1067
1.29M
      0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f,
1068
1.29M
      0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff};
1069
1070
1.29M
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1071
1072
1.29M
  GifByteType NextByte;
1073
1074
  /* The image can't contain more than LZ_BITS per code. */
1075
1.29M
  if (Private->RunningBits > LZ_BITS) {
1076
0
    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1077
0
    return GIF_ERROR;
1078
0
  }
1079
1080
2.52M
  while (Private->CrntShiftState < Private->RunningBits) {
1081
    /* Needs to get more bytes from input stream for next code: */
1082
1.23M
    if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) ==
1083
1.23M
        GIF_ERROR) {
1084
584
      return GIF_ERROR;
1085
584
    }
1086
1.23M
    Private->CrntShiftDWord |= ((unsigned long)NextByte)
1087
1.23M
                               << Private->CrntShiftState;
1088
1.23M
    Private->CrntShiftState += 8;
1089
1.23M
  }
1090
1.29M
  *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1091
1092
1.29M
  Private->CrntShiftDWord >>= Private->RunningBits;
1093
1.29M
  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.29M
  if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1101
1.29M
      ++Private->RunningCode > Private->MaxCode1 &&
1102
1.29M
      Private->RunningBits < LZ_BITS) {
1103
366k
    Private->MaxCode1 <<= 1;
1104
366k
    Private->RunningBits++;
1105
366k
  }
1106
1.29M
  return GIF_OK;
1107
1.29M
}
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.23M
                             GifByteType *NextByte) {
1117
1.23M
  if (Buf[0] == 0) {
1118
    /* Needs to read the next buffer - this one is empty: */
1119
    /* coverity[check_return] */
1120
89.0k
    if (InternalRead(GifFile, Buf, 1) != 1) {
1121
393
      GifFile->Error = D_GIF_ERR_READ_FAILED;
1122
393
      return GIF_ERROR;
1123
393
    }
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
88.6k
    if (Buf[0] == 0) {
1129
74
      GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1130
74
      return GIF_ERROR;
1131
74
    }
1132
88.6k
    if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1133
117
      GifFile->Error = D_GIF_ERR_READ_FAILED;
1134
117
      return GIF_ERROR;
1135
117
    }
1136
88.4k
    *NextByte = Buf[1];
1137
88.4k
    Buf[1] = 2; /* We use now the second place as last char read! */
1138
88.4k
    Buf[0]--;
1139
1.14M
  } else {
1140
1.14M
    *NextByte = Buf[Buf[1]++];
1141
1.14M
    Buf[0]--;
1142
1.14M
  }
1143
1144
1.23M
  return GIF_OK;
1145
1.23M
}
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
927
void DGifDecreaseImageCounter(GifFileType *GifFile) {
1154
927
  GifFile->ImageCount--;
1155
927
  if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) {
1156
823
    free(GifFile->SavedImages[GifFile->ImageCount].RasterBits);
1157
823
  }
1158
1159
  // Realloc array according to the new image counter.
1160
927
  SavedImage *correct_saved_images = (SavedImage *)reallocarray(
1161
927
      GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage));
1162
927
  if (correct_saved_images != NULL) {
1163
72
    GifFile->SavedImages = correct_saved_images;
1164
72
  }
1165
927
}
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.86k
int DGifSlurp(GifFileType *GifFile) {
1173
1.86k
  size_t ImageSize;
1174
1.86k
  GifRecordType RecordType;
1175
1.86k
  SavedImage *sp;
1176
1.86k
  GifByteType *ExtData;
1177
1.86k
  int ExtFunction;
1178
1179
1.86k
  GifFile->ExtensionBlocks = NULL;
1180
1.86k
  GifFile->ExtensionBlockCount = 0;
1181
1182
96.7k
  do {
1183
96.7k
    if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
1184
201
      return (GIF_ERROR);
1185
201
    }
1186
1187
96.5k
    switch (RecordType) {
1188
78.8k
    case IMAGE_DESC_RECORD_TYPE:
1189
78.8k
      if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
1190
199
        return (GIF_ERROR);
1191
199
      }
1192
1193
78.6k
      sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1194
      /* Allocate memory for the image */
1195
78.6k
      if (sp->ImageDesc.Width <= 0 ||
1196
78.6k
          sp->ImageDesc.Height <= 0 ||
1197
78.6k
          sp->ImageDesc.Width >
1198
78.5k
              (INT_MAX / sp->ImageDesc.Height)) {
1199
104
        DGifDecreaseImageCounter(GifFile);
1200
104
        return GIF_ERROR;
1201
104
      }
1202
78.4k
      ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1203
1204
78.4k
      if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1205
0
        DGifDecreaseImageCounter(GifFile);
1206
0
        return GIF_ERROR;
1207
0
      }
1208
78.4k
      sp->RasterBits = (unsigned char *)reallocarray(
1209
78.4k
          NULL, ImageSize, sizeof(GifPixelType));
1210
1211
78.4k
      if (sp->RasterBits == NULL) {
1212
0
        DGifDecreaseImageCounter(GifFile);
1213
0
        return GIF_ERROR;
1214
0
      }
1215
1216
78.4k
      if (sp->ImageDesc.Interlace) {
1217
71.5k
        int i, j;
1218
        /*
1219
         * The way an interlaced image should be read -
1220
         * offsets and jumps...
1221
         */
1222
71.5k
        static const int InterlacedOffset[] = {0, 4, 2,
1223
71.5k
                                               1};
1224
71.5k
        static const int InterlacedJumps[] = {8, 8, 4,
1225
71.5k
                                              2};
1226
        /* Need to perform 4 passes on the image */
1227
356k
        for (i = 0; i < 4; i++) {
1228
285k
          for (j = InterlacedOffset[i];
1229
1.03M
               j < sp->ImageDesc.Height;
1230
745k
               j += InterlacedJumps[i]) {
1231
745k
            if (DGifGetLine(
1232
745k
                    GifFile,
1233
745k
                    sp->RasterBits +
1234
745k
                        j * sp->ImageDesc
1235
745k
                                .Width,
1236
745k
                    sp->ImageDesc.Width) ==
1237
745k
                GIF_ERROR) {
1238
419
              DGifDecreaseImageCounter(
1239
419
                  GifFile);
1240
419
              return GIF_ERROR;
1241
419
            }
1242
745k
          }
1243
285k
        }
1244
71.5k
      } else {
1245
6.92k
        if (DGifGetLine(GifFile, sp->RasterBits,
1246
6.92k
                        ImageSize) == GIF_ERROR) {
1247
404
          DGifDecreaseImageCounter(GifFile);
1248
404
          return GIF_ERROR;
1249
404
        }
1250
6.92k
      }
1251
1252
77.6k
      if (GifFile->ExtensionBlocks) {
1253
12.7k
        sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1254
12.7k
        sp->ExtensionBlockCount =
1255
12.7k
            GifFile->ExtensionBlockCount;
1256
1257
12.7k
        GifFile->ExtensionBlocks = NULL;
1258
12.7k
        GifFile->ExtensionBlockCount = 0;
1259
12.7k
      }
1260
77.6k
      break;
1261
1262
17.3k
    case EXTENSION_RECORD_TYPE:
1263
17.3k
      if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) ==
1264
17.3k
          GIF_ERROR) {
1265
45
        return (GIF_ERROR);
1266
45
      }
1267
      /* Create an extension block with our data */
1268
17.3k
      if (ExtData != NULL) {
1269
15.2k
        if (GifAddExtensionBlock(
1270
15.2k
                &GifFile->ExtensionBlockCount,
1271
15.2k
                &GifFile->ExtensionBlocks, ExtFunction,
1272
15.2k
                ExtData[0], &ExtData[1]) == GIF_ERROR) {
1273
0
          return (GIF_ERROR);
1274
0
        }
1275
15.2k
      }
1276
99.0k
      for (;;) {
1277
99.0k
        if (DGifGetExtensionNext(GifFile, &ExtData) ==
1278
99.0k
            GIF_ERROR) {
1279
175
          return (GIF_ERROR);
1280
175
        }
1281
98.8k
        if (ExtData == NULL) {
1282
17.1k
          break;
1283
17.1k
        }
1284
        /* Continue the extension block */
1285
81.6k
        if (GifAddExtensionBlock(
1286
81.6k
                &GifFile->ExtensionBlockCount,
1287
81.6k
                &GifFile->ExtensionBlocks,
1288
81.6k
                CONTINUE_EXT_FUNC_CODE, ExtData[0],
1289
81.6k
                &ExtData[1]) == GIF_ERROR) {
1290
0
          return (GIF_ERROR);
1291
0
        }
1292
81.6k
      }
1293
17.1k
      break;
1294
1295
17.1k
    case TERMINATE_RECORD_TYPE:
1296
315
      break;
1297
1298
0
    default: /* Should be trapped by DGifGetRecordType */
1299
0
      break;
1300
96.5k
    }
1301
96.5k
  } while (RecordType != TERMINATE_RECORD_TYPE);
1302
1303
  /* Sanity check for corrupted file */
1304
315
  if (GifFile->ImageCount == 0) {
1305
88
    GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1306
88
    return (GIF_ERROR);
1307
88
  }
1308
1309
227
  return (GIF_OK);
1310
315
}
1311
1312
/* end */