Browse Source

filesystem: zip: fix memory leak (not freed info)

pull/2/head
Mr0maks 6 years ago
parent
commit
b32de42ab7
  1. 120
      engine/common/filesystem.c
  2. 83
      engine/common/filesystem.h

120
engine/common/filesystem.c

@ -109,20 +109,20 @@ typedef struct pack_s
typedef struct zipfile_s typedef struct zipfile_s
{ {
char name[MAX_SYSPATH]; char name[MAX_SYSPATH];
fs_offset_t offset; // offset of local file header fs_offset_t offset; // offset of local file header
fs_offset_t size; //original file size fs_offset_t size; //original file size
fs_offset_t compressed_size; // compressed file size fs_offset_t compressed_size; // compressed file size
} zipfile_t; } zipfile_t;
typedef struct zip_s typedef struct zip_s
{ {
string filename; string filename;
byte *mempool; byte *mempool;
file_t *handle; file_t *handle;
int numfiles; int numfiles;
time_t filetime; time_t filetime;
zipfile_t *files; zipfile_t *files;
} zip_t; } zip_t;
typedef struct searchpath_s 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 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 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 ); 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 byte *W_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
static wfile_t *W_Open( const char *filename, int *errorcode ); static wfile_t *W_Open( const char *filename, int *errorcode );
static qboolean FS_SysFolderExists( const char *path ); 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 ); Con_Reportf( "%s couldn't open\n", zipfile );
if( error ) if( error )
*error = ZIP_LOAD_COULDNT_OPEN; *error = ZIP_LOAD_COULDNT_OPEN;
Zip_Close( zip ); Zip_Close( zip );
return NULL; return NULL;
} }
@ -714,6 +715,8 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
if( ZIP_HEADER_EOCD != signature ) if( ZIP_HEADER_EOCD != signature )
{ {
Con_Reportf( "Cannot find EOCD in %s. Zip file corrupted.\n", zipfile ); Con_Reportf( "Cannot find EOCD in %s. Zip file corrupted.\n", zipfile );
if(error)
*error = ZIP_LOAD_BAD_HEADER;
Zip_Close( zip ); Zip_Close( zip );
return NULL; return NULL;
} }
@ -735,6 +738,9 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
if( header_cdf.signature != ZIP_HEADER_CDF ) if( header_cdf.signature != ZIP_HEADER_CDF )
{ {
Con_Reportf( "CDF signature mismatch in %s. Zip file corrupted.\n", zipfile ); 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 ); Zip_Close( zip );
return NULL; return NULL;
} }
@ -800,6 +806,10 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
int index; int index;
zip_header_t header; zip_header_t header;
zipfile_t *file = NULL; 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; 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 ) if( header.extrafield_len )
FS_Seek( search->zip->handle, header.extrafield_len, SEEK_CUR ); FS_Seek( search->zip->handle, header.extrafield_len, SEEK_CUR );
byte *buffer = Mem_Malloc( search->zip->mempool, file->size + 1 ); decompressed_buffer = Mem_Malloc( search->zip->mempool, file->size + 1 );
buffer[file->size] = '\0';
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_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 ); Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
Mem_Free( buffer ); Mem_Free( decompressed_buffer );
return NULL; return NULL;
} }
@ -853,7 +861,7 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
if( sizeptr ) *sizeptr = file->size; if( sizeptr ) *sizeptr = file->size;
return buffer; return decompressed_buffer;
} }
if( header.compression_flags == ZIP_COMPRESSION_DEFLATED ) 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 ) if( header.extrafield_len )
FS_Seek( search->zip->handle, header.extrafield_len, SEEK_CUR ); 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 ) if( zlib_result == Z_OK )
{ {
Mem_Free( compresed_buffer ); // finaly free compressed buffer Mem_Free( compressed_buffer ); // finaly free compressed buffer
dword test_crc;
CRC32_Init( &test_crc ); 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 ) if( final_crc != header.crc32 )
{ {
Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name ); Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
Mem_Free( decompresed_buffer ); Mem_Free( decompressed_buffer );
return NULL; return NULL;
} }
if( sizeptr ) *sizeptr = file->size; if( sizeptr ) *sizeptr = file->size;
return decompresed_buffer; return decompressed_buffer;
} else if( zlib_result == Z_DATA_ERROR ) } else if( zlib_result == Z_DATA_ERROR )
{ {
Con_Reportf( S_ERROR "Zip_LoadFile: %s : compressed file data corrupted.\n", file->name ); Con_Reportf( S_ERROR "Zip_LoadFile: %s : compressed file data corrupted.\n", file->name );
Mem_Free( compresed_buffer ); Mem_Free( compressed_buffer );
Mem_Free( decompresed_buffer ); Mem_Free( decompressed_buffer );
return NULL; return NULL;
} }
} else }
else
{ {
Con_Reportf( S_ERROR "Zip_LoadFile: %s : file compressed with unknown algorithm.\n", file->name ); Con_Reportf( S_ERROR "Zip_LoadFile: %s : file compressed with unknown algorithm.\n", file->name );
return NULL; return NULL;
@ -1065,13 +1072,15 @@ qboolean FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int
search->next = fs_searchpaths; search->next = fs_searchpaths;
search->flags |= flags; search->flags |= flags;
fs_searchpaths = search; fs_searchpaths = search;
Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles ); Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles );
return true; return true;
} else { }
else
{
if( errorcode != ZIP_LOAD_NO_FILES ) if( errorcode != ZIP_LOAD_NO_FILES )
Con_Reportf( S_ERROR "FS_AddZip_Fullpath: unable to load zip \"%s\"\n", zipfile ); 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; return search;
} }
} }
else if(search->zip) else if( search->zip )
{ {
for(int i = 0; search->zip->numfiles > i; i++) for( int i = 0; search->zip->numfiles > i; i++)
{ {
if( !Q_stricmp( search->zip->files[i].name, name ) ) if( !Q_stricmp( search->zip->files[i].name, name ) )
{ {
if( index ) if( index )
*index = i; *index = i;
return search; return search;
} }
} }
} else { } else
{
char netpath[MAX_SYSPATH]; char netpath[MAX_SYSPATH];
Q_sprintf( netpath, "%s%s", search->filename, name ); 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 ); buf = W_LoadFile( path, &filesize, gamedironly );
if( !buf ) if( !buf )
buf = Zip_LoadFile(path, &filesize, gamedironly); buf = Zip_LoadFile(path, &filesize, gamedironly);
} }
if( filesizeptr ) if( filesizeptr )

83
engine/common/filesystem.h

@ -139,68 +139,61 @@ typedef struct
#pragma pack( 1 ) #pragma pack( 1 )
typedef struct zip_header_s typedef struct zip_header_s
{ {
uint signature; // little endian ZIP_HEADER unsigned int signature; // little endian ZIP_HEADER
u_int16_t version; // version of pkzip need to unpack unsigned short version; // version of pkzip need to unpack
u_int16_t flags; // flags (16 bits == 16 flags) unsigned short flags; // flags (16 bits == 16 flags)
u_int16_t compression_flags; // compression flags (bits) unsigned short compression_flags; // compression flags (bits)
uint dos_date; // file modification time and file modification date unsigned int dos_date; // file modification time and file modification date
uint crc32; //crc32 unsigned int crc32; //crc32
uint compressed_size; unsigned int compressed_size;
uint uncompressed_size; unsigned int uncompressed_size;
u_int16_t filename_len; unsigned short filename_len;
u_int16_t extrafield_len; unsigned short extrafield_len;
} zip_header_t; } zip_header_t;
#pragma pack( )
/* /*
in zip64 comp and uncompr size == 0xffffffff remeber this in zip64 comp and uncompr size == 0xffffffff remeber this
compressed and uncompress filesize stored in extra field compressed and uncompress filesize stored in extra field
*/ */
#pragma pack( 1 )
typedef struct zip_header_extra_s typedef struct zip_header_extra_s
{ {
uint signature; // ZIP_HEADER_SPANNED unsigned int signature; // ZIP_HEADER_SPANNED
uint crc32; unsigned int crc32;
uint compressed_size; unsigned int compressed_size;
uint uncompressed_size; unsigned int uncompressed_size;
} zip_header_extra_t; } zip_header_extra_t;
#pragma pack( )
#pragma pack( 1 )
typedef struct zip_cdf_header_s typedef struct zip_cdf_header_s
{ {
uint signature; unsigned int signature;
u_int16_t version; unsigned short version;
u_int16_t version_need; unsigned short version_need;
u_int16_t generalPurposeBitFlag; unsigned short generalPurposeBitFlag;
u_int16_t flags; unsigned short flags;
u_int16_t modification_time; unsigned short modification_time;
u_int16_t modification_date; unsigned short modification_date;
uint crc32; unsigned int crc32;
uint compressed_size; unsigned int compressed_size;
uint uncompressed_size; unsigned int uncompressed_size;
u_int16_t filename_len; unsigned short filename_len;
u_int16_t extrafield_len; unsigned short extrafield_len;
u_int16_t file_commentary_len; unsigned short file_commentary_len;
u_int16_t disk_start; unsigned short disk_start;
u_int16_t internal_attr; unsigned short internal_attr;
uint external_attr; unsigned int external_attr;
uint local_header_offset; unsigned int local_header_offset;
} zip_cdf_header_t; } zip_cdf_header_t;
#pragma pack ( )
#pragma pack( 1 )
typedef struct zip_header_eocd_s typedef struct zip_header_eocd_s
{ {
u_int16_t disk_number; unsigned short disk_number;
u_int16_t start_disk_number; unsigned short start_disk_number;
u_int16_t number_central_directory_record; unsigned short number_central_directory_record;
u_int16_t total_central_directory_record; unsigned short total_central_directory_record;
uint size_of_central_directory; unsigned int size_of_central_directory;
uint central_directory_offset; unsigned int central_directory_offset;
u_int16_t commentary_len; unsigned short commentary_len;
} zip_header_eocd_t; } zip_header_eocd_t;
#pragma pack( ) #pragma pack( )

Loading…
Cancel
Save