mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-02-01 21:30:57 +00:00
fixed long pk3 entry names causing crashes
when an entry was broken, pack_t::buildBuffer and fs_packFiles would end up wrong
This commit is contained in:
parent
7bfc5d9487
commit
2e3f12c9a2
2 changed files with 52 additions and 15 deletions
|
@ -23,6 +23,8 @@ chg: on Windows, a fatal error will move the early console window to the foregro
|
||||||
chg: com_hunkMegs doesn't have a maximum value anymore
|
chg: com_hunkMegs doesn't have a maximum value anymore
|
||||||
a value too high would reset it and the engine might fail to load with the default value
|
a value too high would reset it and the engine might fail to load with the default value
|
||||||
|
|
||||||
|
fix: broken pk3 files could cause crashes (entry names too long) and mess up the FS
|
||||||
|
|
||||||
fix: using /demo when running a listen server would load the map and then abort playback
|
fix: using /demo when running a listen server would load the map and then abort playback
|
||||||
|
|
||||||
fix: no longer making local copies of all the system info cvars of the current server
|
fix: no longer making local copies of all the system info cvars of the current server
|
||||||
|
|
|
@ -1526,6 +1526,17 @@ ZIP FILE LOADING
|
||||||
==========================================================================
|
==========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static const char* FS_GetFileName( const char* filePath )
|
||||||
|
{
|
||||||
|
for ( int i = strlen(filePath) - 1; i >= 0; i-- ) {
|
||||||
|
if ( filePath[i] == '/' || filePath[i] == '\\' ) {
|
||||||
|
return filePath + i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
FS_LoadZipFile
|
FS_LoadZipFile
|
||||||
|
@ -1534,7 +1545,7 @@ Creates a new pak_t in the search chain for the contents
|
||||||
of a zip file.
|
of a zip file.
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static pack_t *FS_LoadZipFile( char *zipfile, const char *basename )
|
static pack_t *FS_LoadZipFile( const char *zipfile, const char *basename )
|
||||||
{
|
{
|
||||||
unzFile uf;
|
unzFile uf;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1544,6 +1555,8 @@ static pack_t *FS_LoadZipFile( char *zipfile, const char *basename )
|
||||||
int i, len;
|
int i, len;
|
||||||
long hash;
|
long hash;
|
||||||
int fs_numHeaderLongs;
|
int fs_numHeaderLongs;
|
||||||
|
int fileCount;
|
||||||
|
char* filename_lastchar = &filename_inzip[sizeof(filename_inzip) - 1];
|
||||||
|
|
||||||
fs_numHeaderLongs = 0;
|
fs_numHeaderLongs = 0;
|
||||||
|
|
||||||
|
@ -1553,29 +1566,42 @@ static pack_t *FS_LoadZipFile( char *zipfile, const char *basename )
|
||||||
if (err != UNZ_OK)
|
if (err != UNZ_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fs_packFiles += gi.number_entry;
|
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
unzGoToFirstFile(uf);
|
unzGoToFirstFile(uf);
|
||||||
|
fileCount = 0;
|
||||||
|
|
||||||
for (i = 0; i < gi.number_entry; i++)
|
for (i = 0; i < gi.number_entry; i++)
|
||||||
{
|
{
|
||||||
|
*filename_lastchar = '\0';
|
||||||
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
|
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
|
||||||
if (err != UNZ_OK) {
|
if (err != UNZ_OK) {
|
||||||
|
Com_Printf("^3FS_LoadZipFile: ^7Can't read past entry %d in '%s'\n", i, FS_GetFileName(zipfile));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (*filename_lastchar != '\0') {
|
||||||
|
Com_Printf("^3FS_LoadZipFile: ^7Entry %d's name is too long in '%s'\n", i, FS_GetFileName(zipfile));
|
||||||
|
unzGoToNextFile(uf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
len += strlen(filename_inzip) + 1;
|
len += strlen(filename_inzip) + 1;
|
||||||
unzGoToNextFile(uf);
|
unzGoToNextFile(uf);
|
||||||
|
fileCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileInPack_t* buildBuffer = (fileInPack_t*)Z_Malloc( (gi.number_entry * sizeof( fileInPack_t )) + len );
|
if ( !fileCount ) {
|
||||||
char* namePtr = ((char*)buildBuffer) + gi.number_entry * sizeof( fileInPack_t );
|
unzClose(uf);
|
||||||
int* fs_headerLongs = (int*)Z_Malloc( ( gi.number_entry + 1 ) * sizeof(int) );
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInPack_t* buildBuffer = (fileInPack_t*)Z_Malloc( (fileCount * sizeof( fileInPack_t )) + len );
|
||||||
|
char* namePtr = ((char*)buildBuffer) + fileCount * sizeof( fileInPack_t );
|
||||||
|
int* fs_headerLongs = (int*)Z_Malloc( ( fileCount + 1 ) * sizeof(int) );
|
||||||
fs_headerLongs[ fs_numHeaderLongs++ ] = LittleLong( fs_checksumFeed );
|
fs_headerLongs[ fs_numHeaderLongs++ ] = LittleLong( fs_checksumFeed );
|
||||||
|
|
||||||
// get the hash table size from the number of files in the zip
|
// get the hash table size from the number of files in the zip
|
||||||
// because lots of custom pk3 files have less than 32 or 64 files
|
// because lots of custom pk3 files have less than 32 or 64 files
|
||||||
for (i = 1; i <= MAX_FILEHASH_SIZE; i <<= 1) {
|
for (i = 1; i <= MAX_FILEHASH_SIZE; i <<= 1) {
|
||||||
if (i > gi.number_entry) {
|
if (i > fileCount) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1596,39 +1622,48 @@ static pack_t *FS_LoadZipFile( char *zipfile, const char *basename )
|
||||||
}
|
}
|
||||||
|
|
||||||
pack->handle = uf;
|
pack->handle = uf;
|
||||||
pack->numfiles = gi.number_entry;
|
pack->numfiles = fileCount;
|
||||||
unzGoToFirstFile(uf);
|
unzGoToFirstFile(uf);
|
||||||
|
fileCount = 0;
|
||||||
|
|
||||||
for (i = 0; i < gi.number_entry; i++)
|
for (i = 0; i < gi.number_entry; i++)
|
||||||
{
|
{
|
||||||
|
*filename_lastchar = '\0';
|
||||||
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
|
err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
|
||||||
if (err != UNZ_OK) {
|
if (err != UNZ_OK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (*filename_lastchar != '\0') {
|
||||||
|
unzGoToNextFile(uf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (file_info.uncompressed_size > 0) {
|
if (file_info.uncompressed_size > 0) {
|
||||||
fs_headerLongs[fs_numHeaderLongs++] = LittleLong(file_info.crc);
|
fs_headerLongs[fs_numHeaderLongs++] = LittleLong(file_info.crc);
|
||||||
}
|
}
|
||||||
Q_strlwr( filename_inzip );
|
Q_strlwr( filename_inzip );
|
||||||
hash = Q_FileHash( filename_inzip, pack->hashSize );
|
hash = Q_FileHash( filename_inzip, pack->hashSize );
|
||||||
buildBuffer[i].name = namePtr;
|
buildBuffer[fileCount].name = namePtr;
|
||||||
strcpy( buildBuffer[i].name, filename_inzip );
|
strcpy( buildBuffer[fileCount].name, filename_inzip );
|
||||||
namePtr += strlen(filename_inzip) + 1;
|
namePtr += strlen(filename_inzip) + 1;
|
||||||
// store the file position in the zip
|
// store the file position in the zip
|
||||||
unzGetCurrentFileInfoPosition(uf, &buildBuffer[i].pos);
|
unzGetCurrentFileInfoPosition(uf, &buildBuffer[fileCount].pos);
|
||||||
//
|
|
||||||
buildBuffer[i].next = pack->hashTable[hash];
|
buildBuffer[fileCount].next = pack->hashTable[hash];
|
||||||
pack->hashTable[hash] = &buildBuffer[i];
|
pack->hashTable[hash] = &buildBuffer[fileCount];
|
||||||
unzGoToNextFile(uf);
|
unzGoToNextFile(uf);
|
||||||
|
fileCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
pack->checksum = Com_BlockChecksum( &fs_headerLongs[ 1 ], 4 * ( fs_numHeaderLongs - 1 ) );
|
pack->checksum = Com_BlockChecksum( &fs_headerLongs[ 1 ], 4 * ( fs_numHeaderLongs - 1 ) );
|
||||||
pack->pure_checksum = Com_BlockChecksum( fs_headerLongs, 4 * fs_numHeaderLongs );
|
pack->pure_checksum = Com_BlockChecksum( fs_headerLongs, 4 * fs_numHeaderLongs );
|
||||||
pack->checksum = LittleLong( pack->checksum );
|
pack->checksum = LittleLong( pack->checksum );
|
||||||
pack->pure_checksum = LittleLong( pack->pure_checksum );
|
pack->pure_checksum = LittleLong( pack->pure_checksum );
|
||||||
|
pack->buildBuffer = buildBuffer;
|
||||||
|
|
||||||
Z_Free(fs_headerLongs);
|
Z_Free(fs_headerLongs);
|
||||||
|
|
||||||
pack->buildBuffer = buildBuffer;
|
fs_packFiles += fileCount;
|
||||||
|
|
||||||
return pack;
|
return pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue