diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ff3657d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.dds -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b59e2c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*~ +*.trace +ddsinfo +glddstest +afl-mojodds diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c771bf5 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ + +CC?=gcc +CFLAGS?=-Wall -g -O -std=c99 +LDFLAGS?=-g + +CFLAGS+=$(shell sdl2-config --cflags) +CFLAGS+=$(shell pkg-config glew --cflags) + +LDLIBS+=$(shell sdl2-config --libs) +LDLIBS+=$(shell pkg-config glew --libs) + + +.SUFFIXES: .o + +PROGRAMS:=ddsinfo glddstest afl-mojodds + +.PHONY: all clean + +all: $(PROGRAMS) + +clean: + -rm $(PROGRAMS) *.o + + +ddsinfo: ddsinfo.o mojodds.o + $(CC) $(LDFLAGS) -o $@ $^ + + +glddstest: glddstest.o mojodds.o + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + + +afl-mojodds: afl-mojodds.o mojodds.o + $(CC) $(LDFLAGS) -o $@ $^ diff --git a/afl-mojodds.c b/afl-mojodds.c new file mode 100644 index 0000000..4099171 --- /dev/null +++ b/afl-mojodds.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "mojodds.h" + + +// helper for fuzzing with AFL +// if you don't know what this is you don't need it + + +void __afl_manual_init(void); + + +int main(int argc, char *argv[]) { + if (argc != 2) { + return 0; + } + +#ifdef __AFL_HAVE_MANUAL_INIT + __afl_manual_init(); +#endif // __AFL_HAVE_MANUAL_INIT + + const char *filename = argv[1]; + + FILE *f = fopen(filename, "rb"); + if (!f) { + return 1; + } + + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + + char *contents = malloc(size); + size_t readbytes = fread(contents, 1, size, f); + if (readbytes != size) { + free(contents); + fclose(f); + return 2; + } + + fclose(f); + + int isDDS = MOJODDS_isDDS(contents, size); + if (!isDDS) { + return 3; + } + + const void *tex = NULL; + unsigned long texlen = 0; + unsigned int glfmt = 0, w = 0, h = 0, miplevels = 0; + unsigned int cubemapfacelen = 0; + MOJODDS_textureType textureType = 0; + int retval = MOJODDS_getTexture(contents, size, &tex, &texlen, &glfmt, &w, &h, &miplevels, &cubemapfacelen, &textureType); + if (!retval) { + free(contents); + return 4; + } + + uint32_t hash = 0x12345678; + switch (textureType) { + case MOJODDS_TEXTURE_2D: + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getMipMapTexture(miplevel, glfmt, tex, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + continue; + } + + // read every byte to make sure any buffer overflows actually overflow + const char *miptex_ = (const char *) miptex; + for (unsigned int i = 0; i < miptexlen; i++) { + hash = (hash * 65537) ^ miptex_[i]; + } + } + break; + + case MOJODDS_TEXTURE_CUBE: + for (MOJODDS_cubeFace cubeFace = MOJODDS_CUBEFACE_POSITIVE_X; cubeFace <= MOJODDS_CUBEFACE_NEGATIVE_Z; cubeFace++) { + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getCubeFace(cubeFace, miplevel, glfmt, tex, cubemapfacelen, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + continue; + } + + // read every byte to make sure any buffer overflows actually overflow + const char *miptex_ = (const char *) miptex; + for (unsigned int i = 0; i < miptexlen; i++) { + hash = (hash * 65537) ^ miptex_[i]; + } + } + } + break; + + case MOJODDS_TEXTURE_VOLUME: + // TODO: do something with the data + break; + + } + // do something the optimizer is not allowed to remove + printf("0x%08x\n", hash); + + free(contents); + + return 0; +} diff --git a/ddsinfo.c b/ddsinfo.c new file mode 100644 index 0000000..dc9f54d --- /dev/null +++ b/ddsinfo.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include + +#include "mojodds.h" + + +// from http://graphics.stanford.edu/~seander/bithacks.html +static bool isPow2(unsigned int v) { + return v && !(v & (v - 1)); +} + + +static int ddsinfo(const char *filename) { + printf("%s\n", filename); + + FILE *f = fopen(filename, "rb"); + if (!f) { + printf("Error opening %s: %s (%d)\n", filename, strerror(errno), errno); + return 1; + } + + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + + char *contents = malloc(size); + size_t readbytes = fread(contents, 1, size, f); + if (readbytes != size) { + printf("Only got %u of %ld bytes: %s\n", (unsigned int) readbytes, size, strerror(errno)); + free(contents); + fclose(f); + return 2; + } + + fclose(f); + + int isDDS = MOJODDS_isDDS(contents, size); + printf("isDDS: %d\n", isDDS); + if (isDDS) { + const void *tex = NULL; + unsigned long texlen = 0; + unsigned int glfmt = 0, w = 0, h = 0, miplevels = 0; + unsigned int cubemapfacelen = 0; + MOJODDS_textureType textureType = 0; + int retval = MOJODDS_getTexture(contents, size, &tex, &texlen, &glfmt, &w, &h, &miplevels, &cubemapfacelen, &textureType); + if (!retval) { + printf("MOJODDS_getTexture failed\n"); + free(contents); + return 3; + } + + uintptr_t texoffset = ((const char *)(tex)) - contents; + printf("texoffset: %u\n", (unsigned int)(texoffset)); + printf("texlen: %lu\n", texlen); + printf("glfmt: 0x%x\n", glfmt); + printf("width x height: %u x %u\n", w, h); + printf("miplevels: %u\n", miplevels); + printf("textureType: "); + switch (textureType) { + case MOJODDS_TEXTURE_2D: + printf("2D\n"); + printf("\n"); + + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getMipMapTexture(miplevel, glfmt, tex, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getMipMapTexture(%u) error: %d\n", miplevel, retval); + continue; + } + + uintptr_t miptexoffset = ((const char *)(miptex)) - ((const char *)(tex)); + bool npot = !(isPow2(mipW) || isPow2(mipH)); + printf("%4u x %4u %s", mipW, mipH, npot ? "NPOT " : " "); + printf("miptexoffset: %8u ", (unsigned int)(miptexoffset)); + printf("miptexlen: %8lu\n", miptexlen); + } + break; + + case MOJODDS_TEXTURE_CUBE: + printf("cube\n"); + printf("cubemapfacelen: %u\n", cubemapfacelen); + printf("\n"); + + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getCubeFace(MOJODDS_CUBEFACE_POSITIVE_X, miplevel, glfmt, tex, cubemapfacelen, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getMipMapTexture(%u) error: %d\n", miplevel, retval); + continue; + } + + uintptr_t miptexoffset = ((const char *)(miptex)) - ((const char *)(tex)); + bool npot = !(isPow2(mipW) || isPow2(mipH)); + printf("%4u x %4u %s", mipW, mipH, npot ? "NPOT " : " "); + printf("miptexoffset: %8u ", (unsigned int)(miptexoffset)); + printf("miptexlen: %8lu\n", miptexlen); + } + break; + + case MOJODDS_TEXTURE_VOLUME: + printf("volume\n"); + break; + + } + } + + free(contents); + + return 0; +} + + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s DDS-file ...\n", argv[0]); + return 0; + } + + for (int i = 1; i < argc; i++) { + ddsinfo(argv[i]); + } + + return 0; +} diff --git a/glddstest.c b/glddstest.c new file mode 100644 index 0000000..01cda55 --- /dev/null +++ b/glddstest.c @@ -0,0 +1,284 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mojodds.h" + + +// example how to use mojodds with OpenGL +// this program doesn't actually draw anything +// use apitrace, vogl or similar tool to see what it does + + +static void pumpGLErrors(const char *format, ...) { + va_list args; + + va_start(args, format); + + char *tempStr = NULL; + vasprintf(&tempStr, format, args); + + va_end(args); + + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) { + switch (err) { + case GL_INVALID_ENUM: + printf("GL error GL_INVALID_ENUM in \"%s\"\n", tempStr); + break; + + case GL_INVALID_VALUE: + printf("GL error GL_INVALID_VALUE in \"%s\"\n", tempStr); + break; + + default: + printf("Unknown GL error %04x in \"%s\"\n", err, tempStr); + break; + } + } + + free(tempStr); +} + + +static int glddstest(const char *filename) { + printf("%s\n", filename); + if (GLEW_GREMEDY_string_marker) { + glStringMarkerGREMEDY(0, filename); + } + + FILE *f = fopen(filename, "rb"); + if (!f) { + printf("Error opening %s: %s (%d)\n", filename, strerror(errno), errno); + return 1; + } + + fseek(f, 0, SEEK_END); + long size = ftell(f); + fseek(f, 0, SEEK_SET); + + char *contents = malloc(size); + size_t readbytes = fread(contents, 1, size, f); + if (readbytes != size) { + printf("Only got %u of %ld bytes: %s\n", (unsigned int) readbytes, size, strerror(errno)); + free(contents); + fclose(f); + return 2; + } + + fclose(f); + + int isDDS = MOJODDS_isDDS(contents, size); + printf("isDDS: %d\n", isDDS); + if (isDDS) { + const void *tex = NULL; + unsigned long texlen = 0; + unsigned int glfmt = 0, w = 0, h = 0, miplevels = 0; + unsigned int cubemapfacelen = 0; + MOJODDS_textureType textureType = 0; + int retval = MOJODDS_getTexture(contents, size, &tex, &texlen, &glfmt, &w, &h, &miplevels, &cubemapfacelen, &textureType); + if (!retval) { + printf("MOJODDS_getTexture failed\n"); + free(contents); + return 3; + } + + GLint maxTexSize = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); + if (w > maxTexSize || h > maxTexSize) { + printf("Texture too large: %ux%u vs %d\n", w, h, maxTexSize); + return 4; + } + + bool isCompressed = true; + GLenum internalFormat = glfmt; + if (glfmt == GL_BGRA || glfmt == GL_BGR || glfmt == GL_LUMINANCE_ALPHA) { + isCompressed = false; + if (glfmt == GL_BGR) { + internalFormat = GL_RGB8; + } else { + internalFormat = GL_RGBA8; + } + } + + GLuint texId = 0; + // we leak this but don't care + glGenTextures(1, &texId); + + switch (textureType) { + case MOJODDS_TEXTURE_2D: + glBindTexture(GL_TEXTURE_2D, texId); + + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getMipMapTexture(miplevel, glfmt, tex, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getMipMapTexture(%u) error: %d\n", miplevel, retval); + continue; + } + + if (isCompressed) { + glCompressedTexImage2D(GL_TEXTURE_2D, miplevel, glfmt, mipW, mipH, 0, miptexlen, miptex); + pumpGLErrors("glCompressedTexImage2D %u 0x%04x %ux%u %u", miplevel, glfmt, mipW, mipH, miptexlen); + } else { + glTexImage2D(GL_TEXTURE_2D, miplevel, internalFormat, mipW, mipH, 0, glfmt, GL_UNSIGNED_BYTE, miptex); + pumpGLErrors("glTexImage2D %u 0x%04x %ux%u 0x%04x", miplevel, internalFormat, mipW, mipH, glfmt); + } + } + + // and now the same with ARB_texture_storage if it's available + if (GLEW_ARB_texture_storage) { + glGenTextures(1, &texId); + glBindTexture(GL_TEXTURE_2D, texId); + glTexStorage2D(GL_TEXTURE_2D, miplevels, internalFormat, w, h); + pumpGLErrors("glTexStorage2D %u 0x%04x %ux%u", miplevels, internalFormat, w, h); + + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getMipMapTexture(miplevel, glfmt, tex, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getMipMapTexture(%u) error: %d\n", miplevel, retval); + continue; + } + + if (isCompressed) { + glCompressedTexSubImage2D(GL_TEXTURE_2D, miplevel, 0, 0, mipW, mipH, glfmt, miptexlen, miptex); + pumpGLErrors("glCompressedTexSubImage2D %u %ux%u 0x%04x %u", miplevel, mipW, mipH, glfmt, miptexlen); + } else { + glTexSubImage2D(GL_TEXTURE_2D, miplevel, 0, 0, mipW, mipH, glfmt, GL_UNSIGNED_BYTE, miptex); + pumpGLErrors("glTexSubImage2D %u %ux%u 0x%04x", miplevel, mipW, mipH, glfmt); + } + } + } + glBindTexture(GL_TEXTURE_2D, 0); + break; + + case MOJODDS_TEXTURE_CUBE: + glBindTexture(GL_TEXTURE_CUBE_MAP, texId); + + for (MOJODDS_cubeFace cubeFace = MOJODDS_CUBEFACE_POSITIVE_X; cubeFace <= MOJODDS_CUBEFACE_NEGATIVE_Z; cubeFace++) { + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getCubeFace(cubeFace, miplevel, glfmt, tex, cubemapfacelen, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getCubeFace(%d, %u) error: %d\n", cubeFace, miplevel, retval); + continue; + } + + if (isCompressed) { + glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, miplevel, glfmt, mipW, mipH, 0, miptexlen, miptex); + pumpGLErrors("glCompressedTexImage2D %u 0x%04x %ux%u %u", miplevel, glfmt, mipW, mipH, miptexlen); + } else { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, miplevel, internalFormat, mipW, mipH, 0, glfmt, GL_UNSIGNED_BYTE, miptex); + pumpGLErrors("glTexImage2D %u 0x%04x %ux%u 0x%04x", miplevel, internalFormat, mipW, mipH, glfmt); + } + } + } + + // and now the same with ARB_texture_storage if it's available + if (GLEW_ARB_texture_storage) { + glGenTextures(1, &texId); + glBindTexture(GL_TEXTURE_CUBE_MAP, texId); + glTexStorage2D(GL_TEXTURE_CUBE_MAP, miplevels, internalFormat, w, h); + pumpGLErrors("glTexStorage2D %u 0x%04x %ux%u", miplevels, internalFormat, w, h); + + for (MOJODDS_cubeFace cubeFace = MOJODDS_CUBEFACE_POSITIVE_X; cubeFace <= MOJODDS_CUBEFACE_NEGATIVE_Z; cubeFace++) { + for (unsigned int miplevel = 0; miplevel < miplevels; miplevel++) { + const void *miptex = NULL; + unsigned long miptexlen = 0; + unsigned int mipW = 0, mipH = 0; + retval = MOJODDS_getCubeFace(cubeFace, miplevel, glfmt, tex, cubemapfacelen, w, h, &miptex, &miptexlen, &mipW, &mipH); + if (!retval) { + printf("MOJODDS_getCubeFace(%d, %u) error: %d\n", cubeFace, miplevel, retval); + continue; + } + + if (isCompressed) { + glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, miplevel, 0, 0, mipW, mipH, glfmt, miptexlen, miptex); + pumpGLErrors("glCompressedTexSubImage2D %u %ux%u 0x%04x %u", miplevel, mipW, mipH, glfmt, miptexlen); + } else { + glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, miplevel, 0, 0, mipW, mipH, glfmt, GL_UNSIGNED_BYTE, miptex); + pumpGLErrors("glTexSubImage2D %u %ux%u 0x%04x", miplevel, mipW, mipH, glfmt); + } + } + } + } + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + break; + + case MOJODDS_TEXTURE_VOLUME: + // TODO: do something with the data + break; + + } + } + + free(contents); + + return 0; +} + + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s DDS-file ...\n", argv[0]); + return 0; + } + + SDL_Init(SDL_INIT_VIDEO); + SDL_Window *window = SDL_CreateWindow("OpenGL DDS test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_OPENGL); + if (window == NULL) { + printf("Could not create window: %s\n", SDL_GetError()); + return 3; + } + + SDL_GLContext context = SDL_GL_CreateContext(window); + if (context == NULL) { + printf("Could not create GL context: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + return 4; + } + + // clear and swap to get better traces + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SDL_GL_SwapWindow(window); + + glewInit(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SDL_GL_SwapWindow(window); + + // glewInit might raise errors if we got an OpenGL 3.0 context + // ignore them + // in this case glGetError is simpler than fooling around with callbacks + while (glGetError() != GL_NO_ERROR) { } + + for (int i = 1; i < argc; i++) { + glddstest(argv[i]); + // clear and swap to make trace easier to parse + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SDL_GL_SwapWindow(window); + + } + + SDL_GL_DeleteContext(context); + SDL_DestroyWindow(window); + + return 0; +} diff --git a/mojodds.c b/mojodds.c index 7da86f0..08862a0 100644 --- a/mojodds.c +++ b/mojodds.c @@ -22,6 +22,8 @@ typedef uint8_t uint8; typedef uint32_t uint32; #endif +#include "mojodds.h" + #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) #define DDS_MAGIC 0x20534444 // 'DDS ' in littleendian. @@ -40,6 +42,14 @@ typedef uint32_t uint32; #define DDSCAPS_COMPLEX 0x8 #define DDSCAPS_MIPMAP 0x400000 #define DDSCAPS_TEXTURE 0x1000 +#define DDSCAPS2_CUBEMAP 0x200 +#define DDSCAPS2_CUBEMAP_POSITIVEX 0x400 +#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x800 +#define DDSCAPS2_CUBEMAP_POSITIVEY 0x1000 +#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x2000 +#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x4000 +#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x8000 +#define DDSCAPS2_VOLUME 0x200000 #define DDPF_ALPHAPIXELS 0x1 #define DDPF_ALPHA 0x2 #define DDPF_FOURCC 0x4 @@ -59,6 +69,9 @@ typedef uint32_t uint32; #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #define GL_BGR 0x80E0 #define GL_BGRA 0x80E1 +#define GL_LUMINANCE_ALPHA 0x190A + +#define MAX( a, b ) ((a) > (b) ? (a) : (b)) typedef struct { @@ -91,6 +104,25 @@ typedef struct } MOJODDS_Header; +//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn +static const uint32_t MultiplyDeBruijnBitPosition[32] = +{ + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 +}; + + +static uint32_t uintLog2(uint32_t v) { + v |= v >> 1; // first round down to one less than a power of 2 + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27]; +} + + static uint32 readui32(const uint8 **_ptr, size_t *_len) { uint32 retval = 0; @@ -108,13 +140,17 @@ static uint32 readui32(const uint8 **_ptr, size_t *_len) } // readui32 static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, - unsigned int *_glfmt, unsigned int *_miplevels) + unsigned int *_glfmt, unsigned int *_miplevels, + unsigned int *_cubemapfacelen, + MOJODDS_textureType *_textureType) { const uint32 pitchAndLinear = (DDSD_PITCH | DDSD_LINEARSIZE); uint32 width = 0; uint32 height = 0; uint32 calcSize = 0; uint32 calcSizeFlag = DDSD_LINEARSIZE; + uint32 blockDim = 1; + uint32 blockSize = 0; int i; // Files start with magic value... @@ -151,6 +187,17 @@ static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, width = header->dwWidth; height = header->dwHeight; + if (width == 0 || height == 0) + { + return 0; + } + + // check for overflow in width * height + if (height > 0xFFFFFFFFU / width) + { + return 0; + } + header->dwCaps &= ~DDSCAPS_ALPHA; // we'll get this from the pixel format. if (header->dwSize != DDS_HEADERSIZE) // header size must be 124. @@ -161,13 +208,24 @@ static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, return 0; else if ((header->dwCaps & DDSCAPS_TEXTURE) == 0) return 0; - else if (header->dwCaps2 != 0) // !!! FIXME (non-zero with other bits in dwCaps set) - return 0; else if ((header->dwFlags & pitchAndLinear) == pitchAndLinear) return 0; // can't specify both. *_miplevels = (header->dwCaps & DDSCAPS_MIPMAP) ? header->dwMipMapCount : 1; + unsigned int calculatedMipLevels = uintLog2(MAX(width, height)) + 1; + if (*_miplevels == 0) + { + // invalid, calculate it ourselves from size + *_miplevels = calculatedMipLevels; + } + else if (*_miplevels > calculatedMipLevels) + { + // too many mip levels, several would be 1x1 + // file is corrupted + return 0; + } + if (header->ddspf.dwFlags & DDPF_FOURCC) { switch (header->ddspf.dwFourCC) @@ -176,16 +234,22 @@ static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, *_glfmt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; calcSize = ((width ? ((width + 3) / 4) : 1) * 8) * (height ? ((height + 3) / 4) : 1); + blockDim = 4; + blockSize = 8; break; case FOURCC_DXT3: *_glfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; calcSize = ((width ? ((width + 3) / 4) : 1) * 16) * (height ? ((height + 3) / 4) : 1); + blockDim = 4; + blockSize = 16; break; case FOURCC_DXT5: *_glfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; calcSize = ((width ? ((width + 3) / 4) : 1) * 16) * (height ? ((height + 3) / 4) : 1); + blockDim = 4; + blockSize = 16; break; // !!! FIXME: DX10 is an extended header, introduced by DirectX 10. @@ -212,17 +276,27 @@ static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, (header->ddspf.dwABitMask != 0xFF000000) ) return 0; // unsupported. *_glfmt = GL_BGRA; + blockSize = 4; } // if else { if (header->ddspf.dwRGBBitCount != 24) return 0; // unsupported. *_glfmt = GL_BGR; + blockSize = 3; } // else calcSizeFlag = DDSD_PITCH; calcSize = ((width * header->ddspf.dwRGBBitCount) + 7) / 8; - } // else if + } + else if (header->ddspf.dwFlags & (DDPF_LUMINANCE | DDPF_ALPHA) ) + { + *_glfmt = GL_LUMINANCE_ALPHA; + + calcSizeFlag = DDSD_PITCH; + blockSize = 2; + calcSize = ((width * header->ddspf.dwRGBBitCount) + 7) / 8; + } //else if (header->ddspf.dwFlags & DDPF_LUMINANCE) // !!! FIXME //else if (header->ddspf.dwFlags & DDPF_YUV) // !!! FIXME @@ -245,6 +319,88 @@ static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len, header->dwFlags |= calcSizeFlag; } // if + *_textureType = MOJODDS_TEXTURE_2D; + { // figure out texture type. + if (header->dwCaps & DDSCAPS_COMPLEX && + header->dwCaps2 & DDSCAPS2_CUBEMAP && + header->dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX && + header->dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX && + header->dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY && + header->dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY && + header->dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ && + header->dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) + { + *_textureType = MOJODDS_TEXTURE_CUBE; + } + else if (header->dwCaps2 & DDSCAPS2_VOLUME) + { + *_textureType = MOJODDS_TEXTURE_VOLUME; + } + } + + // figure out how much memory makes up a single face mip chain. + if (*_textureType == MOJODDS_TEXTURE_CUBE) + { + uint32 wd = header->dwWidth; + uint32 ht = header->dwHeight; + if (wd != ht) + { + // cube maps must be square + return 0; + } + *_cubemapfacelen = 0; + for (i = 0; i < (int)*_miplevels; i++) + { + uint32_t mipLen = MAX((wd + blockDim - 1) / blockDim, 1) * MAX((ht + blockDim - 1) / blockDim, 1) * blockSize; + if (UINT32_MAX - mipLen < *_cubemapfacelen) { + // data size would overflow 32-bit uint, invalid file + return 0; + } + *_cubemapfacelen += mipLen; + wd >>= 1; + ht >>= 1; + } + + // 6 because cube faces + if (*len < (*_cubemapfacelen) * 6) { + return 0; + } + } + else if (*_textureType == MOJODDS_TEXTURE_2D) + { + // check that file contains enough data like the header says + // TODO: also do this for other texture types + uint32 wd = header->dwWidth; + uint32 ht = header->dwHeight; + uint32_t dataLen = 0; + for (i = 0; i < (int)*_miplevels; i++) + { + uint32_t mipLen = MAX((wd + blockDim - 1) / blockDim, 1) * MAX((ht + blockDim - 1) / blockDim, 1) * blockSize; + if (UINT32_MAX - mipLen < dataLen) { + // data size would overflow 32-bit uint, invalid file + return 0; + } + dataLen += mipLen; + wd >>= 1; + ht >>= 1; + } + + if (*len < dataLen) { + return 0; + } + } + + if (header->dwPitchOrLinearSize > *len) { + // dwPitchOrLinearSize is incorrect + return 0; + } + + if (calcSize > *len) { + // there's not enough data to contain the advertised images + // trying to read mips would fail + return 0; + } + return 1; } // parse_dds @@ -260,12 +416,14 @@ int MOJODDS_isDDS(const void *_ptr, const unsigned long _len) int MOJODDS_getTexture(const void *_ptr, const unsigned long _len, const void **_tex, unsigned long *_texlen, unsigned int *_glfmt, unsigned int *_w, - unsigned int *_h, unsigned int *_miplevels) + unsigned int *_h, unsigned int *_miplevels, + unsigned int *_cubemapfacelen, + MOJODDS_textureType *_textureType) { size_t len = (size_t) _len; const uint8 *ptr = (const uint8 *) _ptr; MOJODDS_Header header; - if (!parse_dds(&header, &ptr, &len, _glfmt, _miplevels)) + if (!parse_dds(&header, &ptr, &len, _glfmt, _miplevels, _cubemapfacelen, _textureType)) return 0; *_tex = (const void *) ptr; @@ -279,5 +437,94 @@ int MOJODDS_getTexture(const void *_ptr, const unsigned long _len, return 1; } // MOJODDS_getTexture +int MOJODDS_getMipMapTexture(unsigned int miplevel, unsigned int glfmt, + const void*_basetex, + unsigned int w, unsigned h, + const void **_tex, unsigned long *_texlen, + unsigned int *_texw, unsigned int *_texh) +{ + int i; + const char* newtex; + unsigned long newtexlen; + unsigned int neww; + unsigned int newh; + uint32 blockDim = 1; + uint32 blockSize = 0; + + switch (glfmt) { + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + blockDim = 4; + blockSize = 8; + break; + + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + blockDim = 4; + blockSize = 16; + break; + + case GL_BGR: + blockSize = 3; + break; + + case GL_BGRA: + blockSize = 4; + break; + + case GL_LUMINANCE_ALPHA: + blockSize = 2; + break; + + default: + assert(!"unsupported GL format"); + break; + } + + assert(blockSize != 0); + + newtex = _basetex; + neww = w; + newh = h; + newtexlen = ((neww + blockDim - 1) / blockDim) * ((newh + blockDim - 1) / blockDim) * blockSize; + + // Calculate size of miplevel + for (i=0; i < miplevel; ++i) + { + // move position to next texture start + newtex += newtexlen; + // calculate texture size + neww >>= 1; + newh >>= 1; + if (neww < 1) neww = 1; + if (newh < 1) newh = 1; + newtexlen = ((neww + blockDim - 1) / blockDim) * ((newh + blockDim - 1) / blockDim) * blockSize; + } // for + + *_tex = newtex; + if (_texlen) { + *_texlen = newtexlen; + } + *_texw = neww; + *_texh = newh; + return 1; +} // MOJODDS_getMipMapTexture + + +int MOJODDS_getCubeFace(MOJODDS_cubeFace cubeFace, unsigned int miplevel, + unsigned int glfmt, const void *_basetex, + unsigned long _cubemapfacelen, unsigned int w, unsigned h, + const void **_tex, unsigned long *_texlen, + unsigned int *_texw, unsigned int *_texh) +{ + // pick correct face + const char *faceBaseTex = (const char *) _basetex; + faceBaseTex = faceBaseTex + cubeFace * _cubemapfacelen; + + + // call MOJODDS_getMipMapTexture to get offset in that face + return MOJODDS_getMipMapTexture(miplevel, glfmt, faceBaseTex, w, h, _tex, _texlen, _texw, _texh); +} + + // end of mojodds.c ... diff --git a/mojodds.h b/mojodds.h index 63c848e..4bbaa48 100644 --- a/mojodds.h +++ b/mojodds.h @@ -6,11 +6,45 @@ extern "C" { #endif +typedef enum MOJODDS_textureType +{ + MOJODDS_TEXTURE_2D, + MOJODDS_TEXTURE_CUBE, + MOJODDS_TEXTURE_VOLUME +} MOJODDS_textureType; + + +/* order and values for these matter, they are used for calculating offsets + lucky for us both DDS and OpengGL order matches */ +typedef enum MOJODDS_cubeFace { + MOJODDS_CUBEFACE_POSITIVE_X, + MOJODDS_CUBEFACE_NEGATIVE_X, + MOJODDS_CUBEFACE_POSITIVE_Y, + MOJODDS_CUBEFACE_NEGATIVE_Y, + MOJODDS_CUBEFACE_POSITIVE_Z, + MOJODDS_CUBEFACE_NEGATIVE_Z +} MOJODDS_cubeFace; + + int MOJODDS_isDDS(const void *_ptr, const unsigned long _len); int MOJODDS_getTexture(const void *_ptr, const unsigned long _len, const void **_tex, unsigned long *_texlen, unsigned int *_glfmt, unsigned int *_w, - unsigned int *_h, unsigned int *_miplevels); + unsigned int *_h, unsigned int *_miplevels, + unsigned int *_cubemapfacelen, + MOJODDS_textureType *_textureType); +int MOJODDS_getMipMapTexture(unsigned int miplevel, unsigned int glfmt, + const void*_basetex, + unsigned int w, unsigned h, + const void **_tex, unsigned long *_texlen, + unsigned int *_texw, unsigned int *_texh); + +int MOJODDS_getCubeFace(MOJODDS_cubeFace cubeFace, unsigned int miplevel, + unsigned int glfmt, const void*_basetex, + unsigned long _cubemapfacelen, unsigned int w, unsigned h, + const void **_tex, unsigned long *_texlen, + unsigned int *_texw, unsigned int *_texh); + #ifdef __cplusplus } diff --git a/testcases/README.txt b/testcases/README.txt new file mode 100644 index 0000000..3e0e37e --- /dev/null +++ b/testcases/README.txt @@ -0,0 +1 @@ +This directory contains AFL-generated minimal test corpus. diff --git a/testcases/afl/05db792f178c7e908a802283050abd98.dds b/testcases/afl/05db792f178c7e908a802283050abd98.dds new file mode 100644 index 0000000..325d309 Binary files /dev/null and b/testcases/afl/05db792f178c7e908a802283050abd98.dds differ diff --git a/testcases/afl/0a11f64bcc401602e5e79a999df048d3.dds b/testcases/afl/0a11f64bcc401602e5e79a999df048d3.dds new file mode 100644 index 0000000..9e8cea2 Binary files /dev/null and b/testcases/afl/0a11f64bcc401602e5e79a999df048d3.dds differ diff --git a/testcases/afl/0c4202655d522702dcc67c77ea3cb191.dds b/testcases/afl/0c4202655d522702dcc67c77ea3cb191.dds new file mode 100644 index 0000000..2b53c4f Binary files /dev/null and b/testcases/afl/0c4202655d522702dcc67c77ea3cb191.dds differ diff --git a/testcases/afl/0f2219fcb50ca9829fb77cce0ea44856.dds b/testcases/afl/0f2219fcb50ca9829fb77cce0ea44856.dds new file mode 100644 index 0000000..2db4b94 Binary files /dev/null and b/testcases/afl/0f2219fcb50ca9829fb77cce0ea44856.dds differ diff --git a/testcases/afl/0fcb7b73d8186a898e0092e47654271a.dds b/testcases/afl/0fcb7b73d8186a898e0092e47654271a.dds new file mode 100644 index 0000000..94ddc08 Binary files /dev/null and b/testcases/afl/0fcb7b73d8186a898e0092e47654271a.dds differ diff --git a/testcases/afl/119624f5b1f58ea64a929d0ed64e01d0.dds b/testcases/afl/119624f5b1f58ea64a929d0ed64e01d0.dds new file mode 100644 index 0000000..333ab3b Binary files /dev/null and b/testcases/afl/119624f5b1f58ea64a929d0ed64e01d0.dds differ diff --git a/testcases/afl/163ea94aedbad4f49e005cdf993f6473.dds b/testcases/afl/163ea94aedbad4f49e005cdf993f6473.dds new file mode 100644 index 0000000..488083f Binary files /dev/null and b/testcases/afl/163ea94aedbad4f49e005cdf993f6473.dds differ diff --git a/testcases/afl/1703611c4b9b1a27d905c049e7576243.dds b/testcases/afl/1703611c4b9b1a27d905c049e7576243.dds new file mode 100644 index 0000000..82d0619 Binary files /dev/null and b/testcases/afl/1703611c4b9b1a27d905c049e7576243.dds differ diff --git a/testcases/afl/17bf5f29dba71bdb503b1aea6bdd9487.dds b/testcases/afl/17bf5f29dba71bdb503b1aea6bdd9487.dds new file mode 100644 index 0000000..643e9cf --- /dev/null +++ b/testcases/afl/17bf5f29dba71bdb503b1aea6bdd9487.dds @@ -0,0 +1 @@ +DDS \ No newline at end of file diff --git a/testcases/afl/19fdce77858d232c279dcc51276eca8f.dds b/testcases/afl/19fdce77858d232c279dcc51276eca8f.dds new file mode 100644 index 0000000..4f33f93 Binary files /dev/null and b/testcases/afl/19fdce77858d232c279dcc51276eca8f.dds differ diff --git a/testcases/afl/201a25cba9a0128190fa3585dfc424ea.dds b/testcases/afl/201a25cba9a0128190fa3585dfc424ea.dds new file mode 100644 index 0000000..925abd7 Binary files /dev/null and b/testcases/afl/201a25cba9a0128190fa3585dfc424ea.dds differ diff --git a/testcases/afl/203d983c68662fab32ff905a78a04eb1.dds b/testcases/afl/203d983c68662fab32ff905a78a04eb1.dds new file mode 100644 index 0000000..7ea6479 Binary files /dev/null and b/testcases/afl/203d983c68662fab32ff905a78a04eb1.dds differ diff --git a/testcases/afl/218140160767b22cd56bc6364d65a1d6.dds b/testcases/afl/218140160767b22cd56bc6364d65a1d6.dds new file mode 100644 index 0000000..3025f13 Binary files /dev/null and b/testcases/afl/218140160767b22cd56bc6364d65a1d6.dds differ diff --git a/testcases/afl/282a9f51de5889808aa01de3ce92b6be.dds b/testcases/afl/282a9f51de5889808aa01de3ce92b6be.dds new file mode 100644 index 0000000..99049b5 Binary files /dev/null and b/testcases/afl/282a9f51de5889808aa01de3ce92b6be.dds differ diff --git a/testcases/afl/30fe9c6da2d33787aa7da13a4034dfc7.dds b/testcases/afl/30fe9c6da2d33787aa7da13a4034dfc7.dds new file mode 100644 index 0000000..ff00724 Binary files /dev/null and b/testcases/afl/30fe9c6da2d33787aa7da13a4034dfc7.dds differ diff --git a/testcases/afl/37cdea783a0a14d1746b46f00d6b9d54.dds b/testcases/afl/37cdea783a0a14d1746b46f00d6b9d54.dds new file mode 100644 index 0000000..f42fec5 Binary files /dev/null and b/testcases/afl/37cdea783a0a14d1746b46f00d6b9d54.dds differ diff --git a/testcases/afl/395f4bca3c89d25157b3e29040b433bc.dds b/testcases/afl/395f4bca3c89d25157b3e29040b433bc.dds new file mode 100644 index 0000000..78620e0 Binary files /dev/null and b/testcases/afl/395f4bca3c89d25157b3e29040b433bc.dds differ diff --git a/testcases/afl/3c65c19da3979db609e9757ed7fe8306.dds b/testcases/afl/3c65c19da3979db609e9757ed7fe8306.dds new file mode 100644 index 0000000..1b76a32 Binary files /dev/null and b/testcases/afl/3c65c19da3979db609e9757ed7fe8306.dds differ diff --git a/testcases/afl/431c2a342d19c4b14aefc1013841b296.dds b/testcases/afl/431c2a342d19c4b14aefc1013841b296.dds new file mode 100644 index 0000000..ab6d3cb Binary files /dev/null and b/testcases/afl/431c2a342d19c4b14aefc1013841b296.dds differ diff --git a/testcases/afl/433e71309e2ee38cde4bfb0a05b65b8a.dds b/testcases/afl/433e71309e2ee38cde4bfb0a05b65b8a.dds new file mode 100644 index 0000000..13018b6 Binary files /dev/null and b/testcases/afl/433e71309e2ee38cde4bfb0a05b65b8a.dds differ diff --git a/testcases/afl/46552713e1f2148581a6faeaa0ff561e.dds b/testcases/afl/46552713e1f2148581a6faeaa0ff561e.dds new file mode 100644 index 0000000..725cd21 Binary files /dev/null and b/testcases/afl/46552713e1f2148581a6faeaa0ff561e.dds differ diff --git a/testcases/afl/477610a50263ec5fe9036d69ee136756.dds b/testcases/afl/477610a50263ec5fe9036d69ee136756.dds new file mode 100644 index 0000000..b0f0e77 Binary files /dev/null and b/testcases/afl/477610a50263ec5fe9036d69ee136756.dds differ diff --git a/testcases/afl/495127e29e0379740c47e842c6c6e072.dds b/testcases/afl/495127e29e0379740c47e842c6c6e072.dds new file mode 100644 index 0000000..eadce1c Binary files /dev/null and b/testcases/afl/495127e29e0379740c47e842c6c6e072.dds differ diff --git a/testcases/afl/4b6ded5b17e410c805f0f924da895939.dds b/testcases/afl/4b6ded5b17e410c805f0f924da895939.dds new file mode 100644 index 0000000..749e366 Binary files /dev/null and b/testcases/afl/4b6ded5b17e410c805f0f924da895939.dds differ diff --git a/testcases/afl/593aab193a321351442164ca0ea559f4.dds b/testcases/afl/593aab193a321351442164ca0ea559f4.dds new file mode 100644 index 0000000..b59d4f5 Binary files /dev/null and b/testcases/afl/593aab193a321351442164ca0ea559f4.dds differ diff --git a/testcases/afl/5b6b2654798e2aa535abb193190b447f.dds b/testcases/afl/5b6b2654798e2aa535abb193190b447f.dds new file mode 100644 index 0000000..c85373a Binary files /dev/null and b/testcases/afl/5b6b2654798e2aa535abb193190b447f.dds differ diff --git a/testcases/afl/5b74bbeec2c15508a0e80a69c379eb6d.dds b/testcases/afl/5b74bbeec2c15508a0e80a69c379eb6d.dds new file mode 100644 index 0000000..6a982a1 Binary files /dev/null and b/testcases/afl/5b74bbeec2c15508a0e80a69c379eb6d.dds differ diff --git a/testcases/afl/5e64e3a18c4b85fce29bf9bd4d7c060c.dds b/testcases/afl/5e64e3a18c4b85fce29bf9bd4d7c060c.dds new file mode 100644 index 0000000..db2fa06 Binary files /dev/null and b/testcases/afl/5e64e3a18c4b85fce29bf9bd4d7c060c.dds differ diff --git a/testcases/afl/5e7eaf737832efcb29a60e0d8ea82ff4.dds b/testcases/afl/5e7eaf737832efcb29a60e0d8ea82ff4.dds new file mode 100644 index 0000000..3e75ea1 Binary files /dev/null and b/testcases/afl/5e7eaf737832efcb29a60e0d8ea82ff4.dds differ diff --git a/testcases/afl/63f709a83c9a4a0c892ebbf82fd59cd2.dds b/testcases/afl/63f709a83c9a4a0c892ebbf82fd59cd2.dds new file mode 100644 index 0000000..4f20681 Binary files /dev/null and b/testcases/afl/63f709a83c9a4a0c892ebbf82fd59cd2.dds differ diff --git a/testcases/afl/6512e08aa5fcdc35e929be8ea9e8a6f7.dds b/testcases/afl/6512e08aa5fcdc35e929be8ea9e8a6f7.dds new file mode 100644 index 0000000..d612b22 Binary files /dev/null and b/testcases/afl/6512e08aa5fcdc35e929be8ea9e8a6f7.dds differ diff --git a/testcases/afl/83af34b71f5d6ad19bcbfe9acbf18f62.dds b/testcases/afl/83af34b71f5d6ad19bcbfe9acbf18f62.dds new file mode 100644 index 0000000..91247c0 Binary files /dev/null and b/testcases/afl/83af34b71f5d6ad19bcbfe9acbf18f62.dds differ diff --git a/testcases/afl/8409e8c0d571650e593874adef716c36.dds b/testcases/afl/8409e8c0d571650e593874adef716c36.dds new file mode 100644 index 0000000..91aba5f Binary files /dev/null and b/testcases/afl/8409e8c0d571650e593874adef716c36.dds differ diff --git a/testcases/afl/8aabdcda9c673d260398c2f956272b6f.dds b/testcases/afl/8aabdcda9c673d260398c2f956272b6f.dds new file mode 100644 index 0000000..c0aa645 Binary files /dev/null and b/testcases/afl/8aabdcda9c673d260398c2f956272b6f.dds differ diff --git a/testcases/afl/8c24243c4aeffb207ce44b48f1edc21a.dds b/testcases/afl/8c24243c4aeffb207ce44b48f1edc21a.dds new file mode 100644 index 0000000..8609973 Binary files /dev/null and b/testcases/afl/8c24243c4aeffb207ce44b48f1edc21a.dds differ diff --git a/testcases/afl/909ec0f19d0f54106c321f1ce4c6630f.dds b/testcases/afl/909ec0f19d0f54106c321f1ce4c6630f.dds new file mode 100644 index 0000000..6a5cfdf Binary files /dev/null and b/testcases/afl/909ec0f19d0f54106c321f1ce4c6630f.dds differ diff --git a/testcases/afl/942bf17a52b646a17f8eefc1a95691fa.dds b/testcases/afl/942bf17a52b646a17f8eefc1a95691fa.dds new file mode 100644 index 0000000..c4adb01 Binary files /dev/null and b/testcases/afl/942bf17a52b646a17f8eefc1a95691fa.dds differ diff --git a/testcases/afl/a465ae66f4cba041e621cb470b142020.dds b/testcases/afl/a465ae66f4cba041e621cb470b142020.dds new file mode 100644 index 0000000..6040d3e Binary files /dev/null and b/testcases/afl/a465ae66f4cba041e621cb470b142020.dds differ diff --git a/testcases/afl/aa0de39a8b690e4a7f38560987637e99.dds b/testcases/afl/aa0de39a8b690e4a7f38560987637e99.dds new file mode 100644 index 0000000..6537727 Binary files /dev/null and b/testcases/afl/aa0de39a8b690e4a7f38560987637e99.dds differ diff --git a/testcases/afl/abb3923183d847dad7f69752b8960607.dds b/testcases/afl/abb3923183d847dad7f69752b8960607.dds new file mode 100644 index 0000000..f412ea9 Binary files /dev/null and b/testcases/afl/abb3923183d847dad7f69752b8960607.dds differ diff --git a/testcases/afl/aca33cb76bd832d6fd5ff5708ceb7c38.dds b/testcases/afl/aca33cb76bd832d6fd5ff5708ceb7c38.dds new file mode 100644 index 0000000..7e7ae9e --- /dev/null +++ b/testcases/afl/aca33cb76bd832d6fd5ff5708ceb7c38.dds @@ -0,0 +1 @@ +DDS 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/testcases/afl/b501178f35b85031e59e62fbe04e3a5e.dds b/testcases/afl/b501178f35b85031e59e62fbe04e3a5e.dds new file mode 100644 index 0000000..a21d315 Binary files /dev/null and b/testcases/afl/b501178f35b85031e59e62fbe04e3a5e.dds differ diff --git a/testcases/afl/b5b6626ec9b59c058560c490921cd629.dds b/testcases/afl/b5b6626ec9b59c058560c490921cd629.dds new file mode 100644 index 0000000..5d93c13 Binary files /dev/null and b/testcases/afl/b5b6626ec9b59c058560c490921cd629.dds differ diff --git a/testcases/afl/c03e46b50ad96266f24b74e89448eacf.dds b/testcases/afl/c03e46b50ad96266f24b74e89448eacf.dds new file mode 100644 index 0000000..36d4628 Binary files /dev/null and b/testcases/afl/c03e46b50ad96266f24b74e89448eacf.dds differ diff --git a/testcases/afl/c82d477cb9d4384e0f489e01e73d5cfc.dds b/testcases/afl/c82d477cb9d4384e0f489e01e73d5cfc.dds new file mode 100644 index 0000000..fb5f19b Binary files /dev/null and b/testcases/afl/c82d477cb9d4384e0f489e01e73d5cfc.dds differ diff --git a/testcases/afl/c96844d2ab2ec78960109fee1b844d0f.dds b/testcases/afl/c96844d2ab2ec78960109fee1b844d0f.dds new file mode 100644 index 0000000..0fe96bf Binary files /dev/null and b/testcases/afl/c96844d2ab2ec78960109fee1b844d0f.dds differ diff --git a/testcases/afl/ce5cdf1a7c4a88f6b6d1a61569045f8f.dds b/testcases/afl/ce5cdf1a7c4a88f6b6d1a61569045f8f.dds new file mode 100644 index 0000000..32386b8 Binary files /dev/null and b/testcases/afl/ce5cdf1a7c4a88f6b6d1a61569045f8f.dds differ diff --git a/testcases/afl/d5ea3bc6d102ea01263a194db3f9628b.dds b/testcases/afl/d5ea3bc6d102ea01263a194db3f9628b.dds new file mode 100644 index 0000000..d5c8b07 Binary files /dev/null and b/testcases/afl/d5ea3bc6d102ea01263a194db3f9628b.dds differ diff --git a/testcases/afl/d6561b29cff3a485b39d3679d313220a.dds b/testcases/afl/d6561b29cff3a485b39d3679d313220a.dds new file mode 100644 index 0000000..4365531 Binary files /dev/null and b/testcases/afl/d6561b29cff3a485b39d3679d313220a.dds differ diff --git a/testcases/afl/d87978191ffbf2e3515af8408669b61e.dds b/testcases/afl/d87978191ffbf2e3515af8408669b61e.dds new file mode 100644 index 0000000..7406a9a Binary files /dev/null and b/testcases/afl/d87978191ffbf2e3515af8408669b61e.dds differ diff --git a/testcases/afl/dc60891559a4ab701d363a3cd8abc4f4.dds b/testcases/afl/dc60891559a4ab701d363a3cd8abc4f4.dds new file mode 100644 index 0000000..73bee14 Binary files /dev/null and b/testcases/afl/dc60891559a4ab701d363a3cd8abc4f4.dds differ diff --git a/testcases/afl/dd3aaf127d6e950882e38217846fb8ca.dds b/testcases/afl/dd3aaf127d6e950882e38217846fb8ca.dds new file mode 100644 index 0000000..c2ea90f Binary files /dev/null and b/testcases/afl/dd3aaf127d6e950882e38217846fb8ca.dds differ diff --git a/testcases/afl/e1cc2a66f59310774b8635077b586c7e.dds b/testcases/afl/e1cc2a66f59310774b8635077b586c7e.dds new file mode 100644 index 0000000..5d22d57 Binary files /dev/null and b/testcases/afl/e1cc2a66f59310774b8635077b586c7e.dds differ diff --git a/testcases/afl/e849e96148e4917ed0264e5e5d760712.dds b/testcases/afl/e849e96148e4917ed0264e5e5d760712.dds new file mode 100644 index 0000000..ad5ab0b Binary files /dev/null and b/testcases/afl/e849e96148e4917ed0264e5e5d760712.dds differ diff --git a/testcases/afl/e92fc456c80b36caed51d32851941234.dds b/testcases/afl/e92fc456c80b36caed51d32851941234.dds new file mode 100644 index 0000000..7d4e0a5 Binary files /dev/null and b/testcases/afl/e92fc456c80b36caed51d32851941234.dds differ diff --git a/testcases/afl/eaf30d2d753f2b3f598e660dbdae89ad.dds b/testcases/afl/eaf30d2d753f2b3f598e660dbdae89ad.dds new file mode 100644 index 0000000..385589a Binary files /dev/null and b/testcases/afl/eaf30d2d753f2b3f598e660dbdae89ad.dds differ diff --git a/testcases/afl/ef28a4f8e8ee11863f4f6c7a79c2ad0f.dds b/testcases/afl/ef28a4f8e8ee11863f4f6c7a79c2ad0f.dds new file mode 100644 index 0000000..85c9f0a Binary files /dev/null and b/testcases/afl/ef28a4f8e8ee11863f4f6c7a79c2ad0f.dds differ diff --git a/testcases/afl/f43e732021bd14d6b9e40174a16addbc.dds b/testcases/afl/f43e732021bd14d6b9e40174a16addbc.dds new file mode 100644 index 0000000..502adff Binary files /dev/null and b/testcases/afl/f43e732021bd14d6b9e40174a16addbc.dds differ diff --git a/testcases/afl/f8f64ac3c235a15101370b0ff8e480c4.dds b/testcases/afl/f8f64ac3c235a15101370b0ff8e480c4.dds new file mode 100644 index 0000000..753a373 Binary files /dev/null and b/testcases/afl/f8f64ac3c235a15101370b0ff8e480c4.dds differ diff --git a/testcases/afl/fa15f384a8dfb780c694aebfceb9187c.dds b/testcases/afl/fa15f384a8dfb780c694aebfceb9187c.dds new file mode 100644 index 0000000..cad4d89 Binary files /dev/null and b/testcases/afl/fa15f384a8dfb780c694aebfceb9187c.dds differ diff --git a/testcases/afl/fa7eb67ca7f68caff90135223a27036d.dds b/testcases/afl/fa7eb67ca7f68caff90135223a27036d.dds new file mode 100644 index 0000000..95116ff Binary files /dev/null and b/testcases/afl/fa7eb67ca7f68caff90135223a27036d.dds differ diff --git a/testcases/afl/fb23381f7e8572945ea981a3ba28ee30.dds b/testcases/afl/fb23381f7e8572945ea981a3ba28ee30.dds new file mode 100644 index 0000000..5d24f01 Binary files /dev/null and b/testcases/afl/fb23381f7e8572945ea981a3ba28ee30.dds differ diff --git a/testcases/afl/ff62989546bfc5218c33c7e9a7086b5c.dds b/testcases/afl/ff62989546bfc5218c33c7e9a7086b5c.dds new file mode 100644 index 0000000..0a2b9ce Binary files /dev/null and b/testcases/afl/ff62989546bfc5218c33c7e9a7086b5c.dds differ