mirror of https://github.com/OpenRCT2/OpenRCT2.git
fix #3558: safely read chunks from S6 files
It appears many saved games have been saved with excess uncompressed data that overflows the S6 structure. This may have been caused by a save bug in an earlier version of OpenRCT2. This will now cap the uncompressed data to the amount expected.
This commit is contained in:
parent
d979e2b607
commit
4298f416d2
|
@ -107,7 +107,7 @@ void S6Importer::LoadSavedGame(SDL_RWops *rw)
|
|||
{
|
||||
auto meh = SDL_RWtell(rw);
|
||||
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.header);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.header, sizeof(_s6.header));
|
||||
if (_s6.header.type != S6_TYPE_SAVEDGAME)
|
||||
{
|
||||
throw Exception("Data is not a saved game.");
|
||||
|
@ -127,21 +127,21 @@ void S6Importer::LoadSavedGame(SDL_RWops *rw)
|
|||
}
|
||||
}
|
||||
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.objects);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.elapsed_months);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.map_elements);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_010E63B8);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.objects, sizeof(_s6.objects));
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.elapsed_months, 16);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.map_elements, sizeof(_s6.map_elements));
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.dword_010E63B8, 3048816);
|
||||
}
|
||||
|
||||
void S6Importer::LoadScenario(SDL_RWops *rw)
|
||||
{
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.header);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.header, sizeof(_s6.header));
|
||||
if (_s6.header.type != S6_TYPE_SCENARIO)
|
||||
{
|
||||
throw Exception("Data is not a scenario.");
|
||||
}
|
||||
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.info);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.info, sizeof(_s6.info));
|
||||
|
||||
// Read packed objects
|
||||
// TODO try to contain this more and not store objects until later
|
||||
|
@ -157,17 +157,17 @@ void S6Importer::LoadScenario(SDL_RWops *rw)
|
|||
}
|
||||
}
|
||||
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.objects);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.elapsed_months);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.map_elements);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_010E63B8);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.guests_in_park);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.last_guests_in_park);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.active_research_types);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.current_expenditure);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value);
|
||||
sawyercoding_read_chunk(rw, (uint8*)&_s6.completed_company_value);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.objects, sizeof(_s6.objects));
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.elapsed_months, 16);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.map_elements, sizeof(_s6.map_elements));
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.dword_010E63B8, 2560076);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.guests_in_park, 4);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.last_guests_in_park, 8);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.park_rating, 2);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.active_research_types, 1082);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.current_expenditure, 16);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.park_value, 4);
|
||||
sawyercoding_read_chunk_safe(rw, &_s6.completed_company_value, 483816);
|
||||
}
|
||||
|
||||
void S6Importer::Import()
|
||||
|
|
|
@ -80,6 +80,21 @@ int sawyercoding_validate_checksum(SDL_RWops* rw)
|
|||
return checksum == fileChecksum;
|
||||
}
|
||||
|
||||
bool sawyercoding_read_chunk_safe(SDL_RWops *rw, void *dst, size_t dstLength)
|
||||
{
|
||||
// Allocate 16 MB to store uncompressed data
|
||||
uint8 *tempBuffer = malloc(16 * 1024 * 1024);
|
||||
size_t uncompressedLength = sawyercoding_read_chunk(rw, tempBuffer);
|
||||
if (uncompressedLength == SIZE_MAX) {
|
||||
free(tempBuffer);
|
||||
return false;
|
||||
} else {
|
||||
memcpy(dst, tempBuffer, min(dstLength, uncompressedLength));
|
||||
free(tempBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067685F
|
||||
|
|
|
@ -46,6 +46,7 @@ enum {
|
|||
|
||||
int sawyercoding_validate_checksum(SDL_RWops* rw);
|
||||
uint32 sawyercoding_calculate_checksum(const uint8* buffer, size_t length);
|
||||
bool sawyercoding_read_chunk_safe(SDL_RWops *rw, void *dst, size_t dstLength);
|
||||
size_t sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer);
|
||||
size_t sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader);
|
||||
size_t sawyercoding_decode_sv4(const uint8 *src, uint8 *dst, size_t length);
|
||||
|
|
Loading…
Reference in New Issue