Fix #4558: Crash on loading invalid scenario

This commit is contained in:
Michał Janiszewski 2016-10-08 22:23:03 +02:00 committed by Ted John
parent 952c412334
commit 3c4a683701
5 changed files with 14 additions and 51 deletions

View File

@ -800,7 +800,7 @@ extern "C"
return 0;
}
size_t chunkSize = sawyercoding_read_chunk(rw, chunk);
size_t chunkSize = sawyercoding_read_chunk_with_size(rw, chunk, 0x600000);
chunk = Memory::Reallocate(chunk, chunkSize);
if (chunk == nullptr)
{

View File

@ -135,7 +135,7 @@ bool object_read_and_load_entries(SDL_RWops* rw)
{
// Read all the object entries
rct_object_entry *entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
sawyercoding_read_chunk(rw, (uint8*)entries);
sawyercoding_read_chunk_with_size(rw, (uint8*)entries, OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
bool result = object_load_entries(entries);
free(entries);
return result;

View File

@ -97,11 +97,20 @@ bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *i
SDL_RWops* rw = SDL_RWFromFile(path, "rb");
if (rw != NULL) {
// Read first chunk
sawyercoding_read_chunk(rw, (uint8*)header);
size_t loaded_size = sawyercoding_read_chunk_with_size(rw, (uint8*)header, sizeof(rct_s6_header));
if (loaded_size != sizeof(rct_s6_header)) {
log_error("Failed to read header from scenario %s", path);
SDL_RWclose(rw);
return false;
}
if (header->type == S6_TYPE_SCENARIO) {
// Read second chunk
sawyercoding_read_chunk(rw, (uint8*)info);
loaded_size = sawyercoding_read_chunk_with_size(rw, (uint8*)info, sizeof(rct_s6_info));
SDL_RWclose(rw);
if (loaded_size != sizeof(rct_s6_info)) {
log_error("Failed to read info from scenario %s", path);
return false;
}
return true;
} else {
log_error("invalid scenario, %s", path);

View File

@ -84,7 +84,7 @@ 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);
size_t uncompressedLength = sawyercoding_read_chunk_with_size(rw, tempBuffer, 16 * 1024 * 1024);
if (uncompressedLength == SIZE_MAX) {
free(tempBuffer);
return false;
@ -109,51 +109,6 @@ bool sawyercoding_skip_chunk(SDL_RWops *rw)
return true;
}
/**
*
* rct2: 0x0067685F
* buffer (esi)
*/
size_t sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer)
{
sawyercoding_chunk_header chunkHeader;
// Read chunk header
if (SDL_RWread(rw, &chunkHeader, sizeof(sawyercoding_chunk_header), 1) != 1) {
log_error("Unable to read chunk header!");
return -1;
}
uint8* src_buffer = malloc(chunkHeader.length);
// Read chunk data
if (SDL_RWread(rw, src_buffer, chunkHeader.length, 1) != 1) {
free(src_buffer);
log_error("Unable to read chunk data!");
return -1;
}
// Decode chunk data
switch (chunkHeader.encoding) {
case CHUNK_ENCODING_NONE:
memcpy(buffer, src_buffer, chunkHeader.length);
break;
case CHUNK_ENCODING_RLE:
chunkHeader.length = (uint32)decode_chunk_rle(src_buffer, buffer, chunkHeader.length);
break;
case CHUNK_ENCODING_RLECOMPRESSED:
chunkHeader.length = (uint32)decode_chunk_rle(src_buffer, buffer, chunkHeader.length);
chunkHeader.length = (uint32)decode_chunk_repeat(buffer, chunkHeader.length);
break;
case CHUNK_ENCODING_ROTATE:
memcpy(buffer, src_buffer, chunkHeader.length);
decode_chunk_rotate(buffer, chunkHeader.length);
break;
}
free(src_buffer);
return chunkHeader.length;
}
/**
*
* rct2: 0x0067685F

View File

@ -51,7 +51,6 @@ 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);
bool sawyercoding_skip_chunk(SDL_RWops *rw);
size_t sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer);
size_t sawyercoding_read_chunk_with_size(SDL_RWops* rw, uint8 *buffer, const size_t buffer_size);
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, size_t bufferLength);