engine: add overflow checks to sprite loader

This commit is contained in:
Alibek Omarov
2026-06-21 13:59:38 +05:00
parent 190fa1bab8
commit 2f776a6173

View File

@@ -62,14 +62,19 @@ static byte *Mod_SwapSpriteFrame( byte *p, byte *end, int bytes )
p += sizeof( frame ); p += sizeof( frame );
// skip pixel data // skip pixel data
if( p + frame.width * frame.height * bytes > end ) if( frame.width < 0 || frame.height < 0 )
return NULL; return NULL;
p += frame.width * frame.height * bytes; size_t pixels = (size_t)frame.width * frame.height * bytes;
if( pixels > (size_t)( end - p ))
return NULL;
p += pixels;
return p; return p;
} }
static byte *Mod_SwapSpriteGroup( byte *p, byte *end, int bytes ) static byte *Mod_SwapSpriteGroup( byte *p, byte *end, int bytes, int min_frames )
{ {
dspritegroup_t group; dspritegroup_t group;
@@ -84,7 +89,7 @@ static byte *Mod_SwapSpriteGroup( byte *p, byte *end, int bytes )
// swap intervals // swap intervals
int numframes = group.numframes; int numframes = group.numframes;
if( p + numframes * sizeof( dspriteinterval_t ) > end ) if( numframes < min_frames || numframes * sizeof( dspriteinterval_t ) > (size_t)( end - p ))
return NULL; return NULL;
for( int i = 0; i < numframes; i++ ) for( int i = 0; i < numframes; i++ )
@@ -144,18 +149,26 @@ static qboolean Mod_SwapSprite( void *buffer, size_t buffersize, int *out_versio
short numi = LittleShort( *(short *)p ); short numi = LittleShort( *(short *)p );
*(short *)p = numi; *(short *)p = numi;
p += sizeof( short ) + numi * 3; p += sizeof( short );
if( numi < 0 || p + numi * 3 > end )
return false;
p += numi * 3;
break; break;
} }
default: default:
return false; return false;
} }
if( numframes < 0 )
return false;
*out_version = version; *out_version = version;
int bytes = ( version == SPRITE_VERSION_32 ) ? 4 : 1; int bytes = ( version == SPRITE_VERSION_32 ) ? 4 : 1;
// swap all frames // swap all frames
for( int i = 0; i < numframes && p && p < end; i++ ) for( int i = 0; i < numframes; i++ )
{ {
dframetype_t frametype; dframetype_t frametype;
@@ -173,12 +186,18 @@ static qboolean Mod_SwapSprite( void *buffer, size_t buffersize, int *out_versio
p = Mod_SwapSpriteFrame( p, end, bytes ); p = Mod_SwapSpriteFrame( p, end, bytes );
break; break;
case FRAME_GROUP: case FRAME_GROUP:
p = Mod_SwapSpriteGroup( p, end, bytes, 1 );
break;
case FRAME_ANGLED: case FRAME_ANGLED:
p = Mod_SwapSpriteGroup( p, end, bytes ); // angled groups are indexed by 0..7 at render time
p = Mod_SwapSpriteGroup( p, end, bytes, 8 );
break; break;
default: default:
return false; return false;
} }
if( !p )
return false;
} }
return true; return true;