diff --git a/engine/common/http/net_http_xash.c b/engine/common/http/net_http_xash.c index 9c79973e..ee2c9765 100644 --- a/engine/common/http/net_http_xash.c +++ b/engine/common/http/net_http_xash.c @@ -30,6 +30,7 @@ HTTP downloader */ #define MAX_HTTP_BUFFER_SIZE (BIT( 16 )) +#define MAX_HTTP_DECOMPRESSED_SIZE ( 64 * 1024 * 1024 ) typedef struct httpserver_s { @@ -471,6 +472,13 @@ static int HTTP_FileDecompress( httpfile_t *file ) decompressed_len = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; } + if( decompressed_len == 0 || decompressed_len > MAX_HTTP_DECOMPRESSED_SIZE ) + { + Con_Printf( S_ERROR "%s: refusing to decompress %s, claimed size out of range (%zu)\n", __func__, file->path, decompressed_len ); + HTTP_FreeFile( file, true ); + return 0; + } + data_in = Mem_Malloc( host.mempool, compressed_len + 1 ); data_out = Mem_Malloc( host.mempool, decompressed_len + 1 ); @@ -500,7 +508,7 @@ static int HTTP_FileDecompress( httpfile_t *file ) if( zlib_result == Z_OK || zlib_result == Z_STREAM_END ) { FS_AllowDirectPaths( true ); - g_fsapi.WriteFile( name, data_out, decompressed_len ); + g_fsapi.WriteFile( name, data_out, decompress_stream.total_out ); FS_AllowDirectPaths( false ); HTTP_FreeFile( file, false ); } diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 84028035..6c3bc126 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -28,6 +28,7 @@ GNU General Public License for more details. #define UDP_HEADER_SIZE 28 +#define MAX_NETCHAN_DECOMPRESSED_SIZE ( 64 * 1024 * 1024 ) #define MAX_NETCHAN_FRAGBUFS_PER_STREAM 8192 #define FLOW_AVG ( 2.0f / 3.0f ) // how fast to converge flow estimates @@ -1313,7 +1314,17 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) if( chan->gs_netchan && chan->use_bz2 && !Q_stricmp( compressor, "bz2" )) { #if !XASH_DEDICATED - byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); + byte *uncompressedBuffer; + + if( uncompressedSize == 0 || uncompressedSize > MAX_NETCHAN_DECOMPRESSED_SIZE ) + { + Con_Printf( S_ERROR "BZ2 fragment uncompressed size out of range: %u for %s\n", uncompressedSize, filename ); + Mem_Free( buffer ); + Netchan_FlushIncoming( chan, FRAG_FILE_STREAM ); + return false; + } + + uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); Con_DPrintf( "Decompressing file %s (%d -> %d bytes)\n", filename, nsize, uncompressedSize ); if( BZ2_bzBuffToBuffDecompress( uncompressedBuffer, &uncompressedSize, buffer, nsize, 1, 0 ) != BZ_OK ) @@ -1336,6 +1347,15 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ) byte *uncompressedBuffer; uncompressedSize = LZSS_GetActualSize( buffer, nsize ); + + if( uncompressedSize == 0 || uncompressedSize > MAX_NETCHAN_DECOMPRESSED_SIZE ) + { + Con_Printf( S_ERROR "LZSS fragment uncompressed size out of range: %u for %s\n", uncompressedSize, filename ); + Mem_Free( buffer ); + Netchan_FlushIncoming( chan, FRAG_FILE_STREAM ); + return false; + } + uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize ); nsize = LZSS_Decompress( buffer, uncompressedBuffer, nsize, uncompressedSize );