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