aboutsummaryrefslogtreecommitdiffstats
path: root/code
diff options
context:
space:
mode:
authorludwig <ludwig@edf5b092-35ff-0310-97b2-ce42778d08ea>2008-02-14 11:12:59 +0000
committerludwig <ludwig@edf5b092-35ff-0310-97b2-ce42778d08ea>2008-02-14 11:12:59 +0000
commit9ce8f89cbcac7539ee4c7313ab1828d95100dce1 (patch)
tree021e753a5e579828e19c5ceb38fdb9967673963f /code
parentd4cc343813c2e5053659dc58aa650f48871b1232 (diff)
downloadioquake3-aero-9ce8f89cbcac7539ee4c7313ab1828d95100dce1.tar.gz
ioquake3-aero-9ce8f89cbcac7539ee4c7313ab1828d95100dce1.zip
make tga decoder more robust against corrupt files
git-svn-id: svn://svn.icculus.org/quake3/trunk@1256 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code')
-rw-r--r--code/renderer/tr_image.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/code/renderer/tr_image.c b/code/renderer/tr_image.c
index b008dae..a478609 100644
--- a/code/renderer/tr_image.c
+++ b/code/renderer/tr_image.c
@@ -1177,21 +1177,34 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
byte *pixbuf;
int row, column;
byte *buf_p;
- byte *buffer;
+ byte *end;
+ byte *buffer = NULL;
TargaHeader targa_header;
byte *targa_rgba;
+ int length;
*pic = NULL;
+ if(width)
+ *width = 0;
+ if(height)
+ *height = 0;
+
//
// load the file
//
- ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
- if (!buffer) {
+ length = ri.FS_ReadFile ( ( char * ) name, (void **)&buffer);
+ if (!buffer || length < 0) {
return;
}
+ if(length < 18)
+ {
+ ri.Error( ERR_DROP, "LoadTGA: header too short (%s)\n", name );
+ }
+
buf_p = buffer;
+ end = buffer + length;
targa_header.id_length = buf_p[0];
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;
numPixels = columns * rows * 4;
- if (width)
- *width = columns;
- if (height)
- *height = rows;
-
if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
{
ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size\n", name);
}
+
targa_rgba = ri.Malloc (numPixels);
- *pic = targa_rgba;
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
+ }
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
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--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
+ if(buf_p + 1 > end)
+ ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)\n", name);
packetHeader= *buf_p++;
packetSize = 1 + (packetHeader & 0x7f);
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) {
case 24:
blue = *buf_p++;
@@ -1350,6 +1372,9 @@ static void LoadTGA ( const char *name, byte **pic, int *width, int *height)
}
}
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++) {
switch (targa_header.pixel_size) {
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);
}
+ if (width)
+ *width = columns;
+ if (height)
+ *height = rows;
+
+ *pic = targa_rgba;
+
ri.FS_FreeFile (buffer);
}
-
static void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).