Fix T62852: crash reading corrupt DDS file.
This commit is contained in:
@@ -1148,6 +1148,12 @@ void *DirectDrawSurface::readData(uint &rsize)
|
|||||||
stream.seek(header_size);
|
stream.seek(header_size);
|
||||||
mem_read(stream, data, 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...
|
// Maybe check if size == rsize? assert() isn't in this scope...
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@@ -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)
|
unsigned int Stream::seek(unsigned int p)
|
||||||
{
|
{
|
||||||
if (p > size) {
|
if (p > size) {
|
||||||
puts(msg_error_seek);
|
set_failed(msg_error_seek);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pos = p;
|
pos = p;
|
||||||
@@ -42,7 +42,7 @@ unsigned int Stream::seek(unsigned int p)
|
|||||||
unsigned int mem_read(Stream & mem, unsigned long long & i)
|
unsigned int mem_read(Stream & mem, unsigned long long & i)
|
||||||
{
|
{
|
||||||
if (mem.pos + 8 > mem.size) {
|
if (mem.pos + 8 > mem.size) {
|
||||||
puts(msg_error_seek);
|
mem.set_failed(msg_error_seek);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
|
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)
|
unsigned int mem_read(Stream & mem, unsigned int & i)
|
||||||
{
|
{
|
||||||
if (mem.pos + 4 > mem.size) {
|
if (mem.pos + 4 > mem.size) {
|
||||||
puts(msg_error_read);
|
mem.set_failed(msg_error_read);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
|
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)
|
unsigned int mem_read(Stream & mem, unsigned short & i)
|
||||||
{
|
{
|
||||||
if (mem.pos + 2 > mem.size) {
|
if (mem.pos + 2 > mem.size) {
|
||||||
puts(msg_error_read);
|
mem.set_failed(msg_error_read);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
|
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)
|
unsigned int mem_read(Stream & mem, unsigned char & i)
|
||||||
{
|
{
|
||||||
if (mem.pos + 1 > mem.size) {
|
if (mem.pos + 1 > mem.size) {
|
||||||
puts(msg_error_read);
|
mem.set_failed(msg_error_read);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
i = (mem.mem + mem.pos)[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)
|
unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt)
|
||||||
{
|
{
|
||||||
if (mem.pos + cnt > mem.size) {
|
if (mem.pos + cnt > mem.size) {
|
||||||
puts(msg_error_read);
|
mem.set_failed(msg_error_read);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
memcpy(i, mem.mem + mem.pos, cnt);
|
memcpy(i, mem.mem + mem.pos, cnt);
|
||||||
mem.pos += cnt;
|
mem.pos += cnt;
|
||||||
return(cnt);
|
return(cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stream::set_failed(const char *msg)
|
||||||
|
{
|
||||||
|
if (!failed) {
|
||||||
|
puts(msg_error_seek);
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -28,8 +28,10 @@ struct Stream {
|
|||||||
unsigned char *mem; // location in memory
|
unsigned char *mem; // location in memory
|
||||||
unsigned int size; // size
|
unsigned int size; // size
|
||||||
unsigned int pos; // current position
|
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);
|
unsigned int seek(unsigned int p);
|
||||||
|
void set_failed(const char *msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int mem_read(Stream & mem, unsigned long long & i);
|
unsigned int mem_read(Stream & mem, unsigned long long & i);
|
||||||
|
@@ -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);
|
ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
|
||||||
|
|
||||||
/* flip compressed texture */
|
/* 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 {
|
else {
|
||||||
ibuf->dds_data.data = NULL;
|
ibuf->dds_data.data = NULL;
|
||||||
|
Reference in New Issue
Block a user