Fix T62852: crash reading corrupt DDS file.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 16 Apr 2019 01:39:29 +0000 (03:39 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 16 Apr 2019 01:41:17 +0000 (03:41 +0200)
source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
source/blender/imbuf/intern/dds/Stream.cpp
source/blender/imbuf/intern/dds/Stream.h
source/blender/imbuf/intern/dds/dds_api.cpp

index 16a7525..76de84c 100644 (file)
@@ -1148,6 +1148,12 @@ void *DirectDrawSurface::readData(uint &rsize)
        stream.seek(header_size);
        mem_read(stream, data, size);
 
+       if (stream.failed) {
+               free(data);
+               data = NULL;
+               rsize = 0;
+       }
+
        // Maybe check if size == rsize? assert() isn't in this scope...
 
        return data;
index 92b5923..d8c2862 100644 (file)
@@ -30,7 +30,7 @@ static const char *msg_error_read = "DDS: trying to read beyond end of stream (c
 unsigned int Stream::seek(unsigned int p)
 {
        if (p > size) {
-               puts(msg_error_seek);
+               set_failed(msg_error_seek);
        }
        else {
                pos = p;
@@ -42,7 +42,7 @@ unsigned int Stream::seek(unsigned int p)
 unsigned int mem_read(Stream & mem, unsigned long long & i)
 {
        if (mem.pos + 8 > mem.size) {
-               puts(msg_error_seek);
+               mem.set_failed(msg_error_seek);
                return(0);
        }
        memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
@@ -53,7 +53,7 @@ unsigned int mem_read(Stream & mem, unsigned long long & i)
 unsigned int mem_read(Stream & mem, unsigned int & i)
 {
        if (mem.pos + 4 > mem.size) {
-               puts(msg_error_read);
+               mem.set_failed(msg_error_read);
                return(0);
        }
        memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
@@ -64,7 +64,7 @@ unsigned int mem_read(Stream & mem, unsigned int & i)
 unsigned int mem_read(Stream & mem, unsigned short & i)
 {
        if (mem.pos + 2 > mem.size) {
-               puts(msg_error_read);
+               mem.set_failed(msg_error_read);
                return(0);
        }
        memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
@@ -75,7 +75,7 @@ unsigned int mem_read(Stream & mem, unsigned short & i)
 unsigned int mem_read(Stream & mem, unsigned char & i)
 {
        if (mem.pos + 1 > mem.size) {
-               puts(msg_error_read);
+               mem.set_failed(msg_error_read);
                return(0);
        }
        i = (mem.mem + mem.pos)[0];
@@ -86,10 +86,18 @@ unsigned int mem_read(Stream & mem, unsigned char & i)
 unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt)
 {
        if (mem.pos + cnt > mem.size) {
-               puts(msg_error_read);
+               mem.set_failed(msg_error_read);
                return(0);
        }
        memcpy(i, mem.mem + mem.pos, cnt);
        mem.pos += cnt;
        return(cnt);
 }
+
+void Stream::set_failed(const char *msg)
+{
+       if (!failed) {
+               puts(msg_error_seek);
+               failed = true;
+       }
+}
index 3da0feb..b9fba2e 100644 (file)
@@ -28,8 +28,10 @@ struct Stream {
        unsigned char *mem; // location in memory
        unsigned int size;  // size
        unsigned int pos;   // current position
-       Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}
+       bool failed;        // error occured when seeking
+       Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0), failed(false) {}
        unsigned int seek(unsigned int p);
+       void set_failed(const char *msg);
 };
 
 unsigned int mem_read(Stream & mem, unsigned long long & i);
index 37577ee..fa88f81 100644 (file)
@@ -165,7 +165,9 @@ struct ImBuf *imb_load_dds(const unsigned char *mem, size_t size, int flags, cha
                        ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
 
                        /* flip compressed texture */
-                       FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
+                       if (ibuf->dds_data.data) {
+                               FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
+                       }
                }
                else {
                        ibuf->dds_data.data = NULL;