mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-11-10 14:41:42 +00:00
make tga decoder more robust against corrupt files
This commit is contained in:
parent
02d842532e
commit
a3d62033d8
1 changed files with 41 additions and 10 deletions
|
@ -1177,21 +1177,34 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
byte *pixbuf;
|
byte *pixbuf;
|
||||||
int row, column;
|
int row, column;
|
||||||
byte *buf_p;
|
byte *buf_p;
|
||||||
byte *buffer;
|
byte *end;
|
||||||
|
byte *buffer = NULL;
|
||||||
TargaHeader targa_header;
|
TargaHeader targa_header;
|
||||||
byte *targa_rgba;
|
byte *targa_rgba;
|
||||||
|
int length;
|
||||||
|
|
||||||
*pic = NULL;
|
*pic = NULL;
|
||||||
|
|
||||||
|
if(width)
|
||||||
|
*width = 0;
|
||||||
|
if(height)
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// load the file
|
// load the file
|
||||||
//
|
//
|
||||||
ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
|
length = ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
|
||||||
if (!buffer) {
|
if (!buffer || length < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(length < 18)
|
||||||
|
{
|
||||||
|
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name );
|
||||||
|
}
|
||||||
|
|
||||||
buf_p = buffer;
|
buf_p = buffer;
|
||||||
|
end = buffer + length;
|
||||||
|
|
||||||
targa_header.id_length = buf_p[0];
|
targa_header.id_length = buf_p[0];
|
||||||
targa_header.colormap_type = buf_p[1];
|
targa_header.colormap_type = buf_p[1];
|
||||||
|
@ -1237,24 +1250,29 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
rows = targa_header.height;
|
rows = targa_header.height;
|
||||||
numPixels = columns * rows * 4;
|
numPixels = columns * rows * 4;
|
||||||
|
|
||||||
if (width)
|
|
||||||
*width = columns;
|
|
||||||
if (height)
|
|
||||||
*height = rows;
|
|
||||||
|
|
||||||
if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
|
if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
|
||||||
{
|
{
|
||||||
ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name);
|
ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
targa_rgba = ri.Malloc (numPixels);
|
targa_rgba = ri.Malloc (numPixels);
|
||||||
*pic = targa_rgba;
|
|
||||||
|
|
||||||
if (targa_header.id_length != 0)
|
if (targa_header.id_length != 0)
|
||||||
|
{
|
||||||
|
if (buf_p + targa_header.id_length > end)
|
||||||
|
ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name );
|
||||||
|
|
||||||
buf_p += targa_header.id_length; // skip TARGA image comment
|
buf_p += targa_header.id_length; // skip TARGA image comment
|
||||||
|
}
|
||||||
|
|
||||||
if ( targa_header.image_type==2 || targa_header.image_type == 3 )
|
if ( targa_header.image_type==2 || targa_header.image_type == 3 )
|
||||||
{
|
{
|
||||||
|
if(buf_p + columns*rows*targa_header.pixel_size/8 > end)
|
||||||
|
{
|
||||||
|
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
// Uncompressed RGB or gray scale image
|
// Uncompressed RGB or gray scale image
|
||||||
for(row=rows-1; row>=0; row--)
|
for(row=rows-1; row>=0; row--)
|
||||||
{
|
{
|
||||||
|
@ -1312,9 +1330,13 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
for(row=rows-1; row>=0; row--) {
|
for(row=rows-1; row>=0; row--) {
|
||||||
pixbuf = targa_rgba + row*columns*4;
|
pixbuf = targa_rgba + row*columns*4;
|
||||||
for(column=0; column<columns; ) {
|
for(column=0; column<columns; ) {
|
||||||
|
if(buf_p + 1 > end)
|
||||||
|
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
|
||||||
packetHeader= *buf_p++;
|
packetHeader= *buf_p++;
|
||||||
packetSize = 1 + (packetHeader & 0x7f);
|
packetSize = 1 + (packetHeader & 0x7f);
|
||||||
if (packetHeader & 0x80) { // run-length packet
|
if (packetHeader & 0x80) { // run-length packet
|
||||||
|
if(buf_p + targa_header.pixel_size/8 > end)
|
||||||
|
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
|
||||||
switch (targa_header.pixel_size) {
|
switch (targa_header.pixel_size) {
|
||||||
case 24:
|
case 24:
|
||||||
blue = *buf_p++;
|
blue = *buf_p++;
|
||||||
|
@ -1350,6 +1372,9 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // non run-length packet
|
else { // non run-length packet
|
||||||
|
|
||||||
|
if(buf_p + targa_header.pixel_size/8*packetSize > end)
|
||||||
|
ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
|
||||||
for(j=0;j<packetSize;j++) {
|
for(j=0;j<packetSize;j++) {
|
||||||
switch (targa_header.pixel_size) {
|
switch (targa_header.pixel_size) {
|
||||||
case 24:
|
case 24:
|
||||||
|
@ -1414,9 +1439,15 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
|
ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = columns;
|
||||||
|
if (height)
|
||||||
|
*height = rows;
|
||||||
|
|
||||||
|
*pic = targa_rgba;
|
||||||
|
|
||||||
ri.FS_FreeFile (buffer);
|
ri.FS_FreeFile (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
|
static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
|
||||||
/* This struct contains the JPEG decompression parameters and pointers to
|
/* This struct contains the JPEG decompression parameters and pointers to
|
||||||
* working space (which is allocated as needed by the JPEG library).
|
* working space (which is allocated as needed by the JPEG library).
|
||||||
|
|
Loading…
Reference in a new issue