From b32de42ab72362e324bec3010dffe0d95f285503 Mon Sep 17 00:00:00 2001 From: Mr0maks Date: Sun, 26 May 2019 23:04:17 +0500 Subject: [PATCH] filesystem: zip: fix memory leak (not freed info) --- engine/common/filesystem.c | 120 ++++++++++++++++++++----------------- engine/common/filesystem.h | 83 ++++++++++++------------- 2 files changed, 103 insertions(+), 100 deletions(-) diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 45e9a6e3..f415f6c1 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -109,20 +109,20 @@ typedef struct pack_s typedef struct zipfile_s { - char name[MAX_SYSPATH]; - fs_offset_t offset; // offset of local file header - fs_offset_t size; //original file size - fs_offset_t compressed_size; // compressed file size + char name[MAX_SYSPATH]; + fs_offset_t offset; // offset of local file header + fs_offset_t size; //original file size + fs_offset_t compressed_size; // compressed file size } zipfile_t; typedef struct zip_s { - string filename; - byte *mempool; - file_t *handle; - int numfiles; - time_t filetime; - zipfile_t *files; + string filename; + byte *mempool; + file_t *handle; + int numfiles; + time_t filetime; + zipfile_t *files; } zip_t; typedef struct searchpath_s @@ -152,6 +152,7 @@ static void FS_InitMemory( void ); static searchpath_t *FS_FindFile( const char *name, int *index, qboolean gamedironly ); static dlumpinfo_t *W_FindLump( wfile_t *wad, const char *name, const char matchtype ); static dpackfile_t *FS_AddFileToPack( const char* name, pack_t *pack, fs_offset_t offset, fs_offset_t size ); +void Zip_Close( zip_t *zip ); static byte *W_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly ); static wfile_t *W_Open( const char *filename, int *errorcode ); static qboolean FS_SysFolderExists( const char *path ); @@ -664,7 +665,7 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) { Con_Reportf( "%s couldn't open\n", zipfile ); if( error ) - *error = ZIP_LOAD_COULDNT_OPEN; + *error = ZIP_LOAD_COULDNT_OPEN; Zip_Close( zip ); return NULL; } @@ -714,6 +715,8 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) if( ZIP_HEADER_EOCD != signature ) { Con_Reportf( "Cannot find EOCD in %s. Zip file corrupted.\n", zipfile ); + if(error) + *error = ZIP_LOAD_BAD_HEADER; Zip_Close( zip ); return NULL; } @@ -735,6 +738,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error ) if( header_cdf.signature != ZIP_HEADER_CDF ) { Con_Reportf( "CDF signature mismatch in %s. Zip file corrupted.\n", zipfile ); + if(error) + *error = ZIP_LOAD_BAD_HEADER; + Mem_Free( info ); Zip_Close( zip ); return NULL; } @@ -800,6 +806,10 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game int index; zip_header_t header; zipfile_t *file = NULL; + byte *compressed_buffer = NULL, *decompressed_buffer = NULL; + unsigned long zlib_dest_size = 0; + int zlib_result = 0; + dword test_crc, final_crc; if( sizeptr ) sizeptr == 0; @@ -829,23 +839,21 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game if( header.extrafield_len ) FS_Seek( search->zip->handle, header.extrafield_len, SEEK_CUR ); - byte *buffer = Mem_Malloc( search->zip->mempool, file->size + 1 ); - - buffer[file->size] = '\0'; + decompressed_buffer = Mem_Malloc( search->zip->mempool, file->size + 1 ); - FS_Read( search->zip->handle, buffer, file->size ); + decompressed_buffer[file->size] = '\0'; - dword test_crc; + FS_Read( search->zip->handle, decompressed_buffer, file->size ); CRC32_Init( &test_crc ); - CRC32_ProcessBuffer( &test_crc, buffer, file->size ); + CRC32_ProcessBuffer( &test_crc, decompressed_buffer, file->size ); - dword final_crc = CRC32_Final(test_crc); + final_crc = CRC32_Final(test_crc); - if(final_crc != header.crc32) + if( final_crc != header.crc32 ) { Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name ); - Mem_Free( buffer ); + Mem_Free( decompressed_buffer ); return NULL; } @@ -853,7 +861,7 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game if( sizeptr ) *sizeptr = file->size; - return buffer; + return decompressed_buffer; } if( header.compression_flags == ZIP_COMPRESSION_DEFLATED ) @@ -865,54 +873,53 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game if( header.extrafield_len ) FS_Seek( search->zip->handle, header.extrafield_len, SEEK_CUR ); - byte *compresed_buffer = Mem_Malloc( search->zip->mempool, file->compressed_size + 1 ); + compressed_buffer = Mem_Malloc( search->zip->mempool, file->compressed_size + 1 ); - compresed_buffer[file->compressed_size] = '\0'; + compressed_buffer[file->compressed_size] = '\0'; - byte *decompresed_buffer = Mem_Malloc( search->zip->mempool, file->size + 1 ); + decompressed_buffer = Mem_Malloc( search->zip->mempool, file->size + 1 ); - compresed_buffer[file->size] = '\0'; + compressed_buffer[file->size] = '\0'; - FS_Read( search->zip->handle, compresed_buffer, file->compressed_size ); + FS_Read( search->zip->handle, compressed_buffer, file->compressed_size ); - unsigned long dest_size = file->size; + zlib_dest_size = file->size; - int zlib_result = uncompress( decompresed_buffer, &dest_size, compresed_buffer, file->compressed_size ); + zlib_result = uncompress( decompressed_buffer, &zlib_dest_size, compressed_buffer, file->compressed_size ); - ASSERT( file->size != dest_size ); + ASSERT( file->size != zlib_dest_size ); if( zlib_result == Z_OK ) { - Mem_Free( compresed_buffer ); // finaly free compressed buffer - - dword test_crc; + Mem_Free( compressed_buffer ); // finaly free compressed buffer CRC32_Init( &test_crc ); - CRC32_ProcessBuffer( &test_crc, decompresed_buffer, file->size ); + CRC32_ProcessBuffer( &test_crc, decompressed_buffer, file->size ); - dword final_crc = CRC32_Final( test_crc ); + final_crc = CRC32_Final( test_crc ); if( final_crc != header.crc32 ) { Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name ); - Mem_Free( decompresed_buffer ); + Mem_Free( decompressed_buffer ); return NULL; } if( sizeptr ) *sizeptr = file->size; - return decompresed_buffer; + return decompressed_buffer; } else if( zlib_result == Z_DATA_ERROR ) { Con_Reportf( S_ERROR "Zip_LoadFile: %s : compressed file data corrupted.\n", file->name ); - Mem_Free( compresed_buffer ); - Mem_Free( decompresed_buffer ); + Mem_Free( compressed_buffer ); + Mem_Free( decompressed_buffer ); return NULL; } - } else + } + else { Con_Reportf( S_ERROR "Zip_LoadFile: %s : file compressed with unknown algorithm.\n", file->name ); return NULL; @@ -1065,13 +1072,15 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int search->next = fs_searchpaths; search->flags |= flags; fs_searchpaths = search; - + Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles ); return true; - } else { + } + else + { if( errorcode != ZIP_LOAD_NO_FILES ) Con_Reportf( S_ERROR "FS_AddZip_Fullpath: unable to load zip \"%s\"\n", zipfile ); - return false; + return false; } } @@ -2380,18 +2389,19 @@ static searchpath_t *FS_FindFile( const char *name, int *index, qboolean gamedir return search; } } - else if(search->zip) - { - for(int i = 0; search->zip->numfiles > i; i++) - { - if( !Q_stricmp( search->zip->files[i].name, name ) ) - { - if( index ) - *index = i; - return search; - } - } - } else { + else if( search->zip ) + { + for( int i = 0; search->zip->numfiles > i; i++) + { + if( !Q_stricmp( search->zip->files[i].name, name ) ) + { + if( index ) + *index = i; + return search; + } + } + } else + { char netpath[MAX_SYSPATH]; Q_sprintf( netpath, "%s%s", search->filename, name ); @@ -2904,7 +2914,7 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro buf = W_LoadFile( path, &filesize, gamedironly ); if( !buf ) - buf = Zip_LoadFile(path, &filesize, gamedironly); + buf = Zip_LoadFile(path, &filesize, gamedironly); } if( filesizeptr ) diff --git a/engine/common/filesystem.h b/engine/common/filesystem.h index c6adc40d..afdaf0ac 100644 --- a/engine/common/filesystem.h +++ b/engine/common/filesystem.h @@ -139,68 +139,61 @@ typedef struct #pragma pack( 1 ) typedef struct zip_header_s { - uint signature; // little endian ZIP_HEADER - u_int16_t version; // version of pkzip need to unpack - u_int16_t flags; // flags (16 bits == 16 flags) - u_int16_t compression_flags; // compression flags (bits) - uint dos_date; // file modification time and file modification date - uint crc32; //crc32 - uint compressed_size; - uint uncompressed_size; - u_int16_t filename_len; - u_int16_t extrafield_len; + unsigned int signature; // little endian ZIP_HEADER + unsigned short version; // version of pkzip need to unpack + unsigned short flags; // flags (16 bits == 16 flags) + unsigned short compression_flags; // compression flags (bits) + unsigned int dos_date; // file modification time and file modification date + unsigned int crc32; //crc32 + unsigned int compressed_size; + unsigned int uncompressed_size; + unsigned short filename_len; + unsigned short extrafield_len; } zip_header_t; -#pragma pack( ) - /* in zip64 comp and uncompr size == 0xffffffff remeber this compressed and uncompress filesize stored in extra field */ -#pragma pack( 1 ) typedef struct zip_header_extra_s { - uint signature; // ZIP_HEADER_SPANNED - uint crc32; - uint compressed_size; - uint uncompressed_size; + unsigned int signature; // ZIP_HEADER_SPANNED + unsigned int crc32; + unsigned int compressed_size; + unsigned int uncompressed_size; } zip_header_extra_t; -#pragma pack( ) -#pragma pack( 1 ) typedef struct zip_cdf_header_s { - uint signature; - u_int16_t version; - u_int16_t version_need; - u_int16_t generalPurposeBitFlag; - u_int16_t flags; - u_int16_t modification_time; - u_int16_t modification_date; - uint crc32; - uint compressed_size; - uint uncompressed_size; - u_int16_t filename_len; - u_int16_t extrafield_len; - u_int16_t file_commentary_len; - u_int16_t disk_start; - u_int16_t internal_attr; - uint external_attr; - uint local_header_offset; + unsigned int signature; + unsigned short version; + unsigned short version_need; + unsigned short generalPurposeBitFlag; + unsigned short flags; + unsigned short modification_time; + unsigned short modification_date; + unsigned int crc32; + unsigned int compressed_size; + unsigned int uncompressed_size; + unsigned short filename_len; + unsigned short extrafield_len; + unsigned short file_commentary_len; + unsigned short disk_start; + unsigned short internal_attr; + unsigned int external_attr; + unsigned int local_header_offset; } zip_cdf_header_t; -#pragma pack ( ) -#pragma pack( 1 ) typedef struct zip_header_eocd_s { - u_int16_t disk_number; - u_int16_t start_disk_number; - u_int16_t number_central_directory_record; - u_int16_t total_central_directory_record; - uint size_of_central_directory; - uint central_directory_offset; - u_int16_t commentary_len; + unsigned short disk_number; + unsigned short start_disk_number; + unsigned short number_central_directory_record; + unsigned short total_central_directory_record; + unsigned int size_of_central_directory; + unsigned int central_directory_offset; + unsigned short commentary_len; } zip_header_eocd_t; #pragma pack( )