1 #include "dgif_fuzz_common.h"
2 #include <iostream>
3
4 using namespace std;
5
6 extern "C" void PrintGifError(int ErrorCode);
7
stub_input_reader(GifFileType * gifFileType,GifByteType * gifByteType,int len)8 int stub_input_reader(GifFileType *gifFileType, GifByteType *gifByteType, int len)
9 {
10 struct gifUserData *gud = (struct gifUserData *)gifFileType->UserData;
11 if (gud->gifLen == 0)
12 return 0;
13 int read_len = (len > gud->gifLen ? gud->gifLen : len);
14 memcpy(gifByteType, gud->gifData, read_len);
15 gud->gifData += read_len;
16 gud->gifLen -= read_len;
17 return read_len;
18 }
19
fuzz_dgif(const uint8_t * Data,size_t Size)20 int fuzz_dgif(const uint8_t *Data, size_t Size)
21 {
22 GifFileType *GifFile;
23 int Error;
24 uint8_t *gifData = (uint8_t *)malloc(Size);
25 memcpy(gifData, Data, Size);
26 struct gifUserData gUData = {Size, gifData};
27
28 GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
29 if (GifFile != NULL)
30 {
31 DGifSlurp(GifFile);
32 DGifCloseFile(GifFile, &Error);
33 }
34 free(gifData);
35 return 0;
36 }
37
fuzz_dgif_extended(const uint8_t * Data,size_t Size)38 int fuzz_dgif_extended(const uint8_t *Data, size_t Size)
39 {
40 GifFileType *GifFile;
41 int Error;
42 uint8_t *gifData = (uint8_t *)malloc(Size);
43 memcpy(gifData, Data, Size);
44 struct gifUserData gUData = {Size, gifData};
45
46 GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
47 if (GifFile == NULL)
48 {
49 free(gifData);
50 return 0;
51 }
52 if (DGifSlurp(GifFile) != GIF_OK)
53 {
54 DGifCloseFile(GifFile, &Error);
55 free(gifData);
56 return 0;
57 }
58 GraphicsControlBlock gcb;
59 for (int i = 0; i < GifFile->ImageCount; i++)
60 {
61 DGifSavedExtensionToGCB(GifFile, i, &gcb);
62 }
63 const ColorMapObject *cmap = GifFile->SColorMap;
64 if (cmap)
65 {
66 DGifSavedExtensionToGCB(GifFile, 0, &gcb);
67 }
68 DGifCloseFile(GifFile, &Error);
69 free(gifData);
70 return 0;
71 }
72
gifColorToColor8888(const GifColorType & color)73 static Color8888 gifColorToColor8888(const GifColorType &color)
74 {
75 return ARGB_TO_COLOR8888(0xff, color.Red, color.Green, color.Blue);
76 }
77
willBeCleared(const GraphicsControlBlock & gcb)78 static bool willBeCleared(const GraphicsControlBlock &gcb)
79 {
80 return gcb.DisposalMode == DISPOSE_BACKGROUND || gcb.DisposalMode == DISPOSE_PREVIOUS;
81 }
82
getDelayMs(GraphicsControlBlock & gcb)83 static long getDelayMs(GraphicsControlBlock &gcb)
84 {
85 return gcb.DelayTime * 10;
86 }
87
fuzz_dgif_ala_android(const uint8_t * Data,size_t Size)88 int fuzz_dgif_ala_android(const uint8_t *Data, size_t Size)
89 {
90 GifFileType *GifFile;
91 int Error;
92 uint8_t *gifData = (uint8_t *)malloc(Size);
93 memcpy(gifData, Data, Size);
94 struct gifUserData gUData = {Size, gifData};
95
96 GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
97 if (GifFile == NULL)
98 {
99 free(gifData);
100 return 0;
101 }
102
103 if (DGifSlurp(GifFile) != GIF_OK)
104 {
105 PrintGifError(GifFile->Error);
106 DGifCloseFile(GifFile, &Error);
107 free(gifData);
108 return 0;
109 }
110
111 long durationMs = 0;
112 int lastUnclearedFrame = -1;
113 bool *preservedFrames = new bool[GifFile->ImageCount];
114 int *restoringFrames = new int[GifFile->ImageCount];
115 int loopCount = 0;
116 Color8888 bgColor = 0;
117
118 GraphicsControlBlock gcb;
119 for (int i = 0; i < GifFile->ImageCount; i++)
120 {
121 const SavedImage &image = GifFile->SavedImages[i];
122 // find the loop extension pair
123 for (int j = 0; (j + 1) < image.ExtensionBlockCount; j++)
124 {
125 ExtensionBlock *eb1 = image.ExtensionBlocks + j;
126 ExtensionBlock *eb2 = image.ExtensionBlocks + j + 1;
127 if (eb1->Function == APPLICATION_EXT_FUNC_CODE
128 // look for "NETSCAPE2.0" app extension
129 && eb1->ByteCount == 11 && !memcmp((const char *)(eb1->Bytes), "NETSCAPE2.0", 11)
130 // verify extension contents and get loop count
131 && eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount == 3 && eb2->Bytes[0] == 1)
132 {
133 loopCount = (int)(eb2->Bytes[2] << 8) + (int)(eb2->Bytes[1]);
134 }
135 }
136 DGifSavedExtensionToGCB(GifFile, i, &gcb);
137 // timing
138 durationMs += getDelayMs(gcb);
139 // preserve logic
140 preservedFrames[i] = false;
141 restoringFrames[i] = -1;
142 if (gcb.DisposalMode == DISPOSE_PREVIOUS && lastUnclearedFrame >= 0)
143 {
144 preservedFrames[lastUnclearedFrame] = true;
145 restoringFrames[i] = lastUnclearedFrame;
146 }
147 if (!willBeCleared(gcb))
148 {
149 lastUnclearedFrame = i;
150 }
151 // Draw
152 // assert(y+8 <= Image->ImageDesc.Height);
153 // assert(x+8*strlen(legend) <= Image->ImageDesc.Width);
154 int imgHeight = GifFile->SavedImages[i].ImageDesc.Height;
155 int imgWidth = GifFile->SavedImages[i].ImageDesc.Width;
156 // TODO: Source x,y, string, and color from fuzzer input
157 int x = 0;
158 int y = 0;
159 int strLen = 6;
160 if (y + 8 <= imgHeight && x + 8 * strLen <= imgWidth)
161 GifDrawText8x8(&GifFile->SavedImages[i], 0, 0, "legend", 42);
162 }
163 #if GIF_DEBUG
164 ALOGD("FrameSequence_gif created with size %d %d, frames %d dur %ld",
165 GifFile->SWidth, GifFile->SHeight, GifFile->ImageCount, durationMs);
166 for (int i = 0; i < GifFile->ImageCount; i++)
167 {
168 DGifSavedExtensionToGCB(GifFile, i, &gcb);
169 ALOGD(" Frame %d - must preserve %d, restore point %d, trans color %d",
170 i, preservedFrames[i], restoringFrames[i], gcb.TransparentColor);
171 }
172 #endif
173 const ColorMapObject *cmap = GifFile->SColorMap;
174 if (cmap)
175 {
176 // calculate bg color
177 GraphicsControlBlock gcb;
178 DGifSavedExtensionToGCB(GifFile, 0, &gcb);
179 if (gcb.TransparentColor == NO_TRANSPARENT_COLOR && GifFile->SBackGroundColor < cmap->ColorCount)
180 {
181 bgColor = gifColorToColor8888(cmap->Colors[GifFile->SBackGroundColor]);
182 }
183 }
184
185 DGifCloseFile(GifFile, &Error);
186 free(gifData);
187 delete[] preservedFrames;
188 delete[] restoringFrames;
189 return 0;
190 }
191