DentonW / DevIL

Developer's Image Library (DevIL) is a cross-platform image library utilizing a simple syntax to load, save, convert, manipulate, filter, and display a variety of images with ease. It is highly portable and has been ported to several platforms.
http://openil.sourceforge.net/
GNU Lesser General Public License v2.1
446 stars 137 forks source link

ilLoadGifL / iReadLump out-of-bounds writing #67

Open Photosounder opened 7 years ago

Photosounder commented 7 years ago

I've isolated a bug that occurs when loading certain GIFs, demonstrated with this minimalistic code:

#include <stdlib.h>
#include <stdio.h>

#ifdef _MSC_VER
#pragma comment (lib, "DevIL.lib")
#pragma comment (lib, "ILU.lib")
#pragma comment (lib, "ILUT.lib")
#endif

#include <IL/il.h>
#include <IL/ilu.h>

char *load_raw_file(const char *path, size_t *size)
{
    FILE *in_file;
    char *data;
    size_t fsize;

    in_file = fopen(path, "rb");

    if (in_file==NULL)
    {
        fprintf(stderr, "File '%s' not found.\n", path);
        return NULL;
    }

    fseek(in_file, 0, SEEK_END);
    fsize = ftell(in_file);
    rewind (in_file);

    data = calloc (fsize+1, sizeof(char));
    fread(data, 1, fsize, in_file);

    fclose(in_file);

    if (size)
        *size = fsize;

    return data;    
}

void load_image_libdevil(const char *in_path)
{
    ILubyte *raw_data;
    size_t size;
    ILboolean err;
    ILuint ImgId;

    raw_data = load_raw_file(in_path, &size);
    if (raw_data==NULL || size==0)
        return ;

    // Initialize DevIL.
    ilInit();
    ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
    ilEnable(IL_ORIGIN_SET);
    ilGenImages(1, &ImgId);     // Generate the main image name to use.
    ilBindImage(ImgId);     // Bind this image name.

    if (!ilLoadL(IL_TYPE_UNKNOWN, raw_data, size))
    {
        fprintf(stderr, "Could not open image from the %d byte buffer in memory\n", size);
        return ;
    }
}

int main()
{
    load_image_libdevil("1477604070775.gif");

    printf("Done.\n");

    return 0;
}

This code loads the GIF's data into memory then lets ilLoadL do its work. Typically it works fine except with some GIFs like this one, the call stack is ilLoadL→ilLoadGifL→iLoadGifInternal→GetImages→iGetPalette→iReadLump, and in iReadLump() the problem occurs at the line *((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i);, the problem being that *((ILubyte*)Buffer + i) is out of bounds for some reason.

I'm using DevIL 1.8.0, and appverif.exe to catch the problem. Here's a ZIP containing the source, the problem causing GIF, the VS2017 project and the DevIL.dll (and its .pdb file).

DevIL_bug.zip