Coverage Report

Created: 2024-05-04 12:45

/proc/self/cwd/external/gif/gifalloc.c
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
3
 GIF construction tools
4
5
SPDX-License-Identifier: MIT
6
7
****************************************************************************/
8
9
#include <stdlib.h>
10
#include <stdio.h>
11
#include <string.h>
12
13
#include "gif_lib.h"
14
#include "gif_lib_private.h"
15
16
0
#define MAX(x, y)    (((x) > (y)) ? (x) : (y))
17
18
/******************************************************************************
19
 Miscellaneous utility functions                          
20
******************************************************************************/
21
22
/* return smallest bitfield size n will fit in */
23
int
24
GifBitSize(int n)
25
3.70k
{
26
3.70k
    register int i;
27
28
20.0k
    for (i = 1; i <= 8; i++)
29
20.0k
        if ((1 << i) >= n)
30
3.70k
            break;
31
3.70k
    return (i);
32
3.70k
}
33
34
/******************************************************************************
35
  Color map object functions                              
36
******************************************************************************/
37
38
/*
39
 * Allocate a color map of given size; initialize with contents of
40
 * ColorMap if that pointer is non-NULL.
41
 */
42
ColorMapObject *
43
GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
44
1.85k
{
45
1.85k
    ColorMapObject *Object;
46
47
    /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to
48
     * make the user know that or should we automatically round up instead? */
49
1.85k
    if (ColorCount != (1 << GifBitSize(ColorCount))) {
50
0
        return ((ColorMapObject *) NULL);
51
0
    }
52
    
53
1.85k
    Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
54
1.85k
    if (Object == (ColorMapObject *) NULL) {
55
0
        return ((ColorMapObject *) NULL);
56
0
    }
57
58
1.85k
    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
59
1.85k
    if (Object->Colors == (GifColorType *) NULL) {
60
0
  free(Object);
61
0
        return ((ColorMapObject *) NULL);
62
0
    }
63
64
1.85k
    Object->ColorCount = ColorCount;
65
1.85k
    Object->BitsPerPixel = GifBitSize(ColorCount);
66
1.85k
    Object->SortFlag = false;
67
68
1.85k
    if (ColorMap != NULL) {
69
736
        memcpy((char *)Object->Colors,
70
736
               (char *)ColorMap, ColorCount * sizeof(GifColorType));
71
736
    }
72
73
1.85k
    return (Object);
74
1.85k
}
75
76
/*******************************************************************************
77
Free a color map object
78
*******************************************************************************/
79
void
80
GifFreeMapObject(ColorMapObject *Object)
81
1.86k
{
82
1.86k
    if (Object != NULL) {
83
1.85k
        (void)free(Object->Colors);
84
1.85k
        (void)free(Object);
85
1.85k
    }
86
1.86k
}
87
88
#ifdef DEBUG
89
void
90
DumpColorMap(ColorMapObject *Object,
91
             FILE * fp)
92
{
93
    if (Object != NULL) {
94
        int i, j, Len = Object->ColorCount;
95
96
        for (i = 0; i < Len; i += 4) {
97
            for (j = 0; j < 4 && j < Len; j++) {
98
                (void)fprintf(fp, "%3d: %02x %02x %02x   ", i + j,
99
            Object->Colors[i + j].Red,
100
            Object->Colors[i + j].Green,
101
            Object->Colors[i + j].Blue);
102
            }
103
            (void)fprintf(fp, "\n");
104
        }
105
    }
106
}
107
#endif /* DEBUG */
108
109
/*******************************************************************************
110
 Compute the union of two given color maps and return it.  If result can't 
111
 fit into 256 colors, NULL is returned, the allocated union otherwise.
112
 ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
113
 copied iff they didn't exist before.  ColorTransIn2 maps the old
114
 ColorIn2 into the ColorUnion color map table./
115
*******************************************************************************/
116
ColorMapObject *
117
GifUnionColorMap(const ColorMapObject *ColorIn1,
118
              const ColorMapObject *ColorIn2,
119
              GifPixelType ColorTransIn2[])
120
0
{
121
0
    int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
122
0
    ColorMapObject *ColorUnion;
123
124
    /*
125
     * We don't worry about duplicates within either color map; if
126
     * the caller wants to resolve those, he can perform unions
127
     * with an empty color map.
128
     */
129
130
    /* Allocate table which will hold the result for sure. */
131
0
    ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
132
0
                               ColorIn2->ColorCount) * 2, NULL);
133
134
0
    if (ColorUnion == NULL)
135
0
        return (NULL);
136
137
    /* 
138
     * Copy ColorIn1 to ColorUnion.
139
     */
140
0
    for (i = 0; i < ColorIn1->ColorCount; i++)
141
0
        ColorUnion->Colors[i] = ColorIn1->Colors[i];
142
0
    CrntSlot = ColorIn1->ColorCount;
143
144
    /* 
145
     * Potentially obnoxious hack:
146
     *
147
     * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
148
     * of table 1.  This is very useful if your display is limited to
149
     * 16 colors.
150
     */
151
0
    while (ColorIn1->Colors[CrntSlot - 1].Red == 0
152
0
           && ColorIn1->Colors[CrntSlot - 1].Green == 0
153
0
           && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
154
0
        CrntSlot--;
155
156
    /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
157
0
    for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
158
        /* Let's see if this color already exists: */
159
0
        for (j = 0; j < ColorIn1->ColorCount; j++)
160
0
            if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], 
161
0
                        sizeof(GifColorType)) == 0)
162
0
                break;
163
164
0
        if (j < ColorIn1->ColorCount)
165
0
            ColorTransIn2[i] = j;    /* color exists in Color1 */
166
0
        else {
167
            /* Color is new - copy it to a new slot: */
168
0
            ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
169
0
            ColorTransIn2[i] = CrntSlot++;
170
0
        }
171
0
    }
172
173
0
    if (CrntSlot > 256) {
174
0
        GifFreeMapObject(ColorUnion);
175
0
        return ((ColorMapObject *) NULL);
176
0
    }
177
178
0
    NewGifBitSize = GifBitSize(CrntSlot);
179
0
    RoundUpTo = (1 << NewGifBitSize);
180
181
0
    if (RoundUpTo != ColorUnion->ColorCount) {
182
0
        register GifColorType *Map = ColorUnion->Colors;
183
184
        /* 
185
         * Zero out slots up to next power of 2.
186
         * We know these slots exist because of the way ColorUnion's
187
         * start dimension was computed.
188
         */
189
0
        for (j = CrntSlot; j < RoundUpTo; j++)
190
0
            Map[j].Red = Map[j].Green = Map[j].Blue = 0;
191
192
        /* perhaps we can shrink the map? */
193
0
        if (RoundUpTo < ColorUnion->ColorCount) {
194
0
            GifColorType *new_map = (GifColorType *)reallocarray(Map,
195
0
                                 RoundUpTo, sizeof(GifColorType));
196
0
            if( new_map == NULL ) {
197
0
                GifFreeMapObject(ColorUnion);
198
0
                return ((ColorMapObject *) NULL);
199
0
            }
200
0
            ColorUnion->Colors = new_map;
201
0
        }
202
0
    }
203
204
0
    ColorUnion->ColorCount = RoundUpTo;
205
0
    ColorUnion->BitsPerPixel = NewGifBitSize;
206
207
0
    return (ColorUnion);
208
0
}
209
210
/*******************************************************************************
211
 Apply a given color translation to the raster bits of an image
212
*******************************************************************************/
213
void
214
GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
215
0
{
216
0
    register int i;
217
0
    register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
218
219
0
    for (i = 0; i < RasterSize; i++)
220
0
        Image->RasterBits[i] = Translation[Image->RasterBits[i]];
221
0
}
222
223
/******************************************************************************
224
 Extension record functions                              
225
******************************************************************************/
226
int
227
GifAddExtensionBlock(int *ExtensionBlockCount,
228
         ExtensionBlock **ExtensionBlocks,
229
         int Function,
230
         unsigned int Len,
231
         unsigned char ExtData[])
232
1.58k
{
233
1.58k
    ExtensionBlock *ep;
234
235
1.58k
    if (*ExtensionBlocks == NULL)
236
139
        *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
237
1.44k
    else {
238
1.44k
        ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
239
1.44k
         (*ExtensionBlocks, (*ExtensionBlockCount + 1),
240
1.44k
                                      sizeof(ExtensionBlock));
241
1.44k
        if( ep_new == NULL )
242
0
            return (GIF_ERROR);
243
1.44k
        *ExtensionBlocks = ep_new;
244
1.44k
    }
245
246
1.58k
    if (*ExtensionBlocks == NULL)
247
0
        return (GIF_ERROR);
248
249
1.58k
    ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
250
251
1.58k
    ep->Function = Function;
252
1.58k
    ep->ByteCount=Len;
253
1.58k
    ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
254
1.58k
    if (ep->Bytes == NULL)
255
0
        return (GIF_ERROR);
256
257
1.58k
    if (ExtData != NULL) {
258
1.58k
        memcpy(ep->Bytes, ExtData, Len);
259
1.58k
    }
260
261
1.58k
    return (GIF_OK);
262
1.58k
}
263
264
void
265
GifFreeExtensions(int *ExtensionBlockCount,
266
      ExtensionBlock **ExtensionBlocks)
267
5.00k
{
268
5.00k
    ExtensionBlock *ep;
269
270
5.00k
    if (*ExtensionBlocks == NULL)
271
4.86k
        return;
272
273
139
    for (ep = *ExtensionBlocks;
274
1.72k
   ep < (*ExtensionBlocks + *ExtensionBlockCount); 
275
1.58k
   ep++)
276
1.58k
        (void)free((char *)ep->Bytes);
277
139
    (void)free((char *)*ExtensionBlocks);
278
139
    *ExtensionBlocks = NULL;
279
139
    *ExtensionBlockCount = 0;
280
139
}
281
282
/******************************************************************************
283
 Image block allocation functions                          
284
******************************************************************************/
285
286
/* Private Function:
287
 * Frees the last image in the GifFile->SavedImages array
288
 */
289
void
290
FreeLastSavedImage(GifFileType *GifFile)
291
0
{
292
0
    SavedImage *sp;
293
    
294
0
    if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
295
0
        return;
296
297
    /* Remove one SavedImage from the GifFile */
298
0
    GifFile->ImageCount--;
299
0
    sp = &GifFile->SavedImages[GifFile->ImageCount];
300
301
    /* Deallocate its Colormap */
302
0
    if (sp->ImageDesc.ColorMap != NULL) {
303
0
        GifFreeMapObject(sp->ImageDesc.ColorMap);
304
0
        sp->ImageDesc.ColorMap = NULL;
305
0
    }
306
307
    /* Deallocate the image data */
308
0
    if (sp->RasterBits != NULL)
309
0
        free((char *)sp->RasterBits);
310
311
    /* Deallocate any extensions */
312
0
    GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
313
314
    /*** FIXME: We could realloc the GifFile->SavedImages structure but is
315
     * there a point to it? Saves some memory but we'd have to do it every
316
     * time.  If this is used in GifFreeSavedImages then it would be inefficient
317
     * (The whole array is going to be deallocated.)  If we just use it when
318
     * we want to free the last Image it's convenient to do it here.
319
     */
320
0
}
321
322
/*
323
 * Append an image block to the SavedImages array  
324
 */
325
SavedImage *
326
GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
327
0
{
328
0
    if (GifFile->SavedImages == NULL)
329
0
        GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
330
0
    else {
331
0
        SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
332
0
                               (GifFile->ImageCount + 1), sizeof(SavedImage));
333
0
        if( newSavedImages == NULL)
334
0
            return ((SavedImage *)NULL);
335
0
        GifFile->SavedImages = newSavedImages;
336
0
    }
337
0
    if (GifFile->SavedImages == NULL)
338
0
        return ((SavedImage *)NULL);
339
0
    else {
340
0
        SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
341
342
0
        if (CopyFrom != NULL) {
343
0
            memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
344
345
            /* 
346
             * Make our own allocated copies of the heap fields in the
347
             * copied record.  This guards against potential aliasing
348
             * problems.
349
             */
350
351
            /* first, the local color map */
352
0
            if (CopyFrom->ImageDesc.ColorMap != NULL) {
353
0
                sp->ImageDesc.ColorMap = GifMakeMapObject(
354
0
                                         CopyFrom->ImageDesc.ColorMap->ColorCount,
355
0
                                         CopyFrom->ImageDesc.ColorMap->Colors);
356
0
                if (sp->ImageDesc.ColorMap == NULL) {
357
0
                    FreeLastSavedImage(GifFile);
358
0
                    return (SavedImage *)(NULL);
359
0
                }
360
0
            }
361
362
            /* next, the raster */
363
0
            sp->RasterBits = (unsigned char *)reallocarray(NULL,
364
0
                                                  (CopyFrom->ImageDesc.Height *
365
0
                                                  CopyFrom->ImageDesc.Width),
366
0
              sizeof(GifPixelType));
367
0
            if (sp->RasterBits == NULL) {
368
0
                FreeLastSavedImage(GifFile);
369
0
                return (SavedImage *)(NULL);
370
0
            }
371
0
            memcpy(sp->RasterBits, CopyFrom->RasterBits,
372
0
                   sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
373
0
                   CopyFrom->ImageDesc.Width);
374
375
            /* finally, the extension blocks */
376
0
            if (CopyFrom->ExtensionBlocks != NULL) {
377
0
                sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
378
0
                                      CopyFrom->ExtensionBlockCount,
379
0
              sizeof(ExtensionBlock));
380
0
                if (sp->ExtensionBlocks == NULL) {
381
0
                    FreeLastSavedImage(GifFile);
382
0
                    return (SavedImage *)(NULL);
383
0
                }
384
0
                memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
385
0
                       sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
386
0
            }
387
0
        }
388
0
        else {
389
0
            memset((char *)sp, '\0', sizeof(SavedImage));
390
0
        }
391
392
0
        return (sp);
393
0
    }
394
0
}
395
396
void
397
GifFreeSavedImages(GifFileType *GifFile)
398
1.43k
{
399
1.43k
    SavedImage *sp;
400
401
1.43k
    if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
402
0
        return;
403
0
    }
404
1.43k
    for (sp = GifFile->SavedImages;
405
4.65k
         sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
406
3.22k
        if (sp->ImageDesc.ColorMap != NULL) {
407
696
            GifFreeMapObject(sp->ImageDesc.ColorMap);
408
696
            sp->ImageDesc.ColorMap = NULL;
409
696
        }
410
411
3.22k
        if (sp->RasterBits != NULL)
412
3.22k
            free((char *)sp->RasterBits);
413
  
414
3.22k
  GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
415
3.22k
    }
416
1.43k
    free((char *)GifFile->SavedImages);
417
1.43k
    GifFile->SavedImages = NULL;
418
1.43k
}
419
420
/* end */