You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.0 KiB
191 lines
5.0 KiB
#include "dgif_fuzz_common.h"
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
|
|
extern "C" void PrintGifError(int ErrorCode);
|
|
|
|
int stub_input_reader(GifFileType *gifFileType, GifByteType *gifByteType, int len)
|
|
{
|
|
struct gifUserData *gud = (struct gifUserData *)gifFileType->UserData;
|
|
if (gud->gifLen == 0)
|
|
return 0;
|
|
int read_len = (len > gud->gifLen ? gud->gifLen : len);
|
|
memcpy(gifByteType, gud->gifData, read_len);
|
|
gud->gifData += read_len;
|
|
gud->gifLen -= read_len;
|
|
return read_len;
|
|
}
|
|
|
|
int fuzz_dgif(const uint8_t *Data, size_t Size)
|
|
{
|
|
GifFileType *GifFile;
|
|
int Error;
|
|
uint8_t *gifData = (uint8_t *)malloc(Size);
|
|
memcpy(gifData, Data, Size);
|
|
struct gifUserData gUData = {Size, gifData};
|
|
|
|
GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
|
|
if (GifFile != NULL)
|
|
{
|
|
DGifSlurp(GifFile);
|
|
DGifCloseFile(GifFile, &Error);
|
|
}
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
|
|
int fuzz_dgif_extended(const uint8_t *Data, size_t Size)
|
|
{
|
|
GifFileType *GifFile;
|
|
int Error;
|
|
uint8_t *gifData = (uint8_t *)malloc(Size);
|
|
memcpy(gifData, Data, Size);
|
|
struct gifUserData gUData = {Size, gifData};
|
|
|
|
GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
|
|
if (GifFile == NULL)
|
|
{
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
if (DGifSlurp(GifFile) != GIF_OK)
|
|
{
|
|
DGifCloseFile(GifFile, &Error);
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
GraphicsControlBlock gcb;
|
|
for (int i = 0; i < GifFile->ImageCount; i++)
|
|
{
|
|
DGifSavedExtensionToGCB(GifFile, i, &gcb);
|
|
}
|
|
const ColorMapObject *cmap = GifFile->SColorMap;
|
|
if (cmap)
|
|
{
|
|
DGifSavedExtensionToGCB(GifFile, 0, &gcb);
|
|
}
|
|
DGifCloseFile(GifFile, &Error);
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
|
|
static Color8888 gifColorToColor8888(const GifColorType &color)
|
|
{
|
|
return ARGB_TO_COLOR8888(0xff, color.Red, color.Green, color.Blue);
|
|
}
|
|
|
|
static bool willBeCleared(const GraphicsControlBlock &gcb)
|
|
{
|
|
return gcb.DisposalMode == DISPOSE_BACKGROUND || gcb.DisposalMode == DISPOSE_PREVIOUS;
|
|
}
|
|
|
|
static long getDelayMs(GraphicsControlBlock &gcb)
|
|
{
|
|
return gcb.DelayTime * 10;
|
|
}
|
|
|
|
int fuzz_dgif_ala_android(const uint8_t *Data, size_t Size)
|
|
{
|
|
GifFileType *GifFile;
|
|
int Error;
|
|
uint8_t *gifData = (uint8_t *)malloc(Size);
|
|
memcpy(gifData, Data, Size);
|
|
struct gifUserData gUData = {Size, gifData};
|
|
|
|
GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error);
|
|
if (GifFile == NULL)
|
|
{
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
|
|
if (DGifSlurp(GifFile) != GIF_OK)
|
|
{
|
|
PrintGifError(GifFile->Error);
|
|
DGifCloseFile(GifFile, &Error);
|
|
free(gifData);
|
|
return 0;
|
|
}
|
|
|
|
long durationMs = 0;
|
|
int lastUnclearedFrame = -1;
|
|
bool *preservedFrames = new bool[GifFile->ImageCount];
|
|
int *restoringFrames = new int[GifFile->ImageCount];
|
|
int loopCount = 0;
|
|
Color8888 bgColor = 0;
|
|
|
|
GraphicsControlBlock gcb;
|
|
for (int i = 0; i < GifFile->ImageCount; i++)
|
|
{
|
|
const SavedImage &image = GifFile->SavedImages[i];
|
|
// find the loop extension pair
|
|
for (int j = 0; (j + 1) < image.ExtensionBlockCount; j++)
|
|
{
|
|
ExtensionBlock *eb1 = image.ExtensionBlocks + j;
|
|
ExtensionBlock *eb2 = image.ExtensionBlocks + j + 1;
|
|
if (eb1->Function == APPLICATION_EXT_FUNC_CODE
|
|
// look for "NETSCAPE2.0" app extension
|
|
&& eb1->ByteCount == 11 && !memcmp((const char *)(eb1->Bytes), "NETSCAPE2.0", 11)
|
|
// verify extension contents and get loop count
|
|
&& eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount == 3 && eb2->Bytes[0] == 1)
|
|
{
|
|
loopCount = (int)(eb2->Bytes[2] << 8) + (int)(eb2->Bytes[1]);
|
|
}
|
|
}
|
|
DGifSavedExtensionToGCB(GifFile, i, &gcb);
|
|
// timing
|
|
durationMs += getDelayMs(gcb);
|
|
// preserve logic
|
|
preservedFrames[i] = false;
|
|
restoringFrames[i] = -1;
|
|
if (gcb.DisposalMode == DISPOSE_PREVIOUS && lastUnclearedFrame >= 0)
|
|
{
|
|
preservedFrames[lastUnclearedFrame] = true;
|
|
restoringFrames[i] = lastUnclearedFrame;
|
|
}
|
|
if (!willBeCleared(gcb))
|
|
{
|
|
lastUnclearedFrame = i;
|
|
}
|
|
// Draw
|
|
// assert(y+8 <= Image->ImageDesc.Height);
|
|
// assert(x+8*strlen(legend) <= Image->ImageDesc.Width);
|
|
int imgHeight = GifFile->SavedImages[i].ImageDesc.Height;
|
|
int imgWidth = GifFile->SavedImages[i].ImageDesc.Width;
|
|
// TODO: Source x,y, string, and color from fuzzer input
|
|
int x = 0;
|
|
int y = 0;
|
|
int strLen = 6;
|
|
if (y + 8 <= imgHeight && x + 8 * strLen <= imgWidth)
|
|
GifDrawText8x8(&GifFile->SavedImages[i], 0, 0, "legend", 42);
|
|
}
|
|
#if GIF_DEBUG
|
|
ALOGD("FrameSequence_gif created with size %d %d, frames %d dur %ld",
|
|
GifFile->SWidth, GifFile->SHeight, GifFile->ImageCount, durationMs);
|
|
for (int i = 0; i < GifFile->ImageCount; i++)
|
|
{
|
|
DGifSavedExtensionToGCB(GifFile, i, &gcb);
|
|
ALOGD(" Frame %d - must preserve %d, restore point %d, trans color %d",
|
|
i, preservedFrames[i], restoringFrames[i], gcb.TransparentColor);
|
|
}
|
|
#endif
|
|
const ColorMapObject *cmap = GifFile->SColorMap;
|
|
if (cmap)
|
|
{
|
|
// calculate bg color
|
|
GraphicsControlBlock gcb;
|
|
DGifSavedExtensionToGCB(GifFile, 0, &gcb);
|
|
if (gcb.TransparentColor == NO_TRANSPARENT_COLOR && GifFile->SBackGroundColor < cmap->ColorCount)
|
|
{
|
|
bgColor = gifColorToColor8888(cmap->Colors[GifFile->SBackGroundColor]);
|
|
}
|
|
}
|
|
|
|
DGifCloseFile(GifFile, &Error);
|
|
free(gifData);
|
|
delete[] preservedFrames;
|
|
delete[] restoringFrames;
|
|
return 0;
|
|
}
|