Changeset - r27067:9886586b97cf
[Not reviewed]
master
0 1 0
Charles Pigott - 20 months ago 2023-04-10 09:32:28
charlespigott@googlemail.com
Add: Some additional debugging information when chunk sizes are incorrect
1 file changed with 27 insertions and 19 deletions:
0 comments (0 inline, 0 general)
src/saveload/saveload.cpp
Show inline comments
 
@@ -648,17 +648,17 @@ static size_t _next_offs;
 
/**
 
 * Iterate through the elements of an array and read the whole thing
 
 * @return The index of the object, or -1 if we have reached the end of current block
 
 */
 
int SlIterateArray()
 
{
 
	int index;
 

	
 
	/* After reading in the whole array inside the loop
 
	 * we must have read in all the data, so we must be at end of current block. */
 
	if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) SlErrorCorrupt("Invalid chunk size");
 
	if (_next_offs != 0 && _sl.reader->GetSize() != _next_offs) {
 
		SlErrorCorruptFmt("Invalid chunk size iterating array - expected to be at position {}, actually at {}", _next_offs, _sl.reader->GetSize());
 
	}
 

	
 
	for (;;) {
 
		uint length = SlReadArrayLength();
 
		if (length == 0) {
 
			assert(!_sl.expect_table_header);
 
			_next_offs = 0;
 
@@ -670,12 +670,13 @@ int SlIterateArray()
 

	
 
		if (_sl.expect_table_header) {
 
			_sl.expect_table_header = false;
 
			return INT32_MAX;
 
		}
 

	
 
		int index;
 
		switch (_sl.block_mode) {
 
			case CH_SPARSE_TABLE:
 
			case CH_SPARSE_ARRAY: index = (int)SlReadSparseIndex(); break;
 
			case CH_TABLE:
 
			case CH_ARRAY:        index = _sl.array_index++; break;
 
			default:
 
@@ -2071,31 +2072,32 @@ void SlGlobList(const SaveLoadTable &slt
 
 * Do something of which I have no idea what it is :P
 
 * @param proc The callback procedure that is called
 
 * @param arg The variable that will be used for the callback procedure
 
 */
 
void SlAutolength(AutolengthProc *proc, void *arg)
 
{
 
	size_t offs;
 

	
 
	assert(_sl.action == SLA_SAVE);
 

	
 
	/* Tell it to calculate the length */
 
	_sl.need_length = NL_CALCLENGTH;
 
	_sl.obj_len = 0;
 
	proc(arg);
 

	
 
	/* Setup length */
 
	_sl.need_length = NL_WANTLENGTH;
 
	SlSetLength(_sl.obj_len);
 

	
 
	offs = _sl.dumper->GetSize() + _sl.obj_len;
 
	size_t start_pos = _sl.dumper->GetSize();
 
	size_t expected_offs = start_pos + _sl.obj_len;
 

	
 
	/* And write the stuff */
 
	proc(arg);
 

	
 
	if (offs != _sl.dumper->GetSize()) SlErrorCorrupt("Invalid chunk size");
 
	if (expected_offs != _sl.dumper->GetSize()) {
 
		SlErrorCorruptFmt("Invalid chunk size when writing autolength block, expected {}, got {}", _sl.obj_len, _sl.dumper->GetSize() - start_pos);
 
	}
 
}
 

	
 
void ChunkHandler::LoadCheck(size_t len) const
 
{
 
	switch (_sl.block_mode) {
 
		case CH_TABLE:
 
@@ -2118,14 +2120,12 @@ void ChunkHandler::LoadCheck(size_t len)
 
 * Load a chunk of data (eg vehicles, stations, etc.)
 
 * @param ch The chunkhandler that will be used for the operation
 
 */
 
static void SlLoadChunk(const ChunkHandler &ch)
 
{
 
	byte m = SlReadByte();
 
	size_t len;
 
	size_t endoffs;
 

	
 
	_sl.block_mode = m & CH_TYPE_MASK;
 
	_sl.obj_len = 0;
 
	_sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
 

	
 
	/* The header should always be at the start. Read the length; the
 
@@ -2143,21 +2143,26 @@ static void SlLoadChunk(const ChunkHandl
 
			break;
 
		case CH_SPARSE_TABLE:
 
		case CH_SPARSE_ARRAY:
 
			ch.Load();
 
			if (_next_offs != 0) SlErrorCorrupt("Invalid array length");
 
			break;
 
		case CH_RIFF:
 
		case CH_RIFF: {
 
			/* Read length */
 
			len = (SlReadByte() << 16) | ((m >> 4) << 24);
 
			size_t len = (SlReadByte() << 16) | ((m >> 4) << 24);
 
			len += SlReadUint16();
 
			_sl.obj_len = len;
 
			endoffs = _sl.reader->GetSize() + len;
 
			size_t start_pos = _sl.reader->GetSize();
 
			size_t endoffs = start_pos + len;
 
			ch.Load();
 
			if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
 

	
 
			if (_sl.reader->GetSize() != endoffs) {
 
				SlErrorCorruptFmt("Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len, _sl.reader->GetSize() - start_pos);
 
			}
 
			break;
 
		}
 
		default:
 
			SlErrorCorrupt("Invalid chunk type");
 
			break;
 
	}
 

	
 
	if (_sl.expect_table_header) SlErrorCorrupt("Table chunk without header");
 
@@ -2168,14 +2173,12 @@ static void SlLoadChunk(const ChunkHandl
 
 * If the chunkhandler is nullptr, the chunk is skipped.
 
 * @param ch The chunkhandler that will be used for the operation
 
 */
 
static void SlLoadCheckChunk(const ChunkHandler &ch)
 
{
 
	byte m = SlReadByte();
 
	size_t len;
 
	size_t endoffs;
 

	
 
	_sl.block_mode = m & CH_TYPE_MASK;
 
	_sl.obj_len = 0;
 
	_sl.expect_table_header = (_sl.block_mode == CH_TABLE || _sl.block_mode == CH_SPARSE_TABLE);
 

	
 
	/* The header should always be at the start. Read the length; the
 
@@ -2191,21 +2194,26 @@ static void SlLoadCheckChunk(const Chunk
 
			ch.LoadCheck();
 
			break;
 
		case CH_SPARSE_TABLE:
 
		case CH_SPARSE_ARRAY:
 
			ch.LoadCheck();
 
			break;
 
		case CH_RIFF:
 
		case CH_RIFF: {
 
			/* Read length */
 
			len = (SlReadByte() << 16) | ((m >> 4) << 24);
 
			size_t len = (SlReadByte() << 16) | ((m >> 4) << 24);
 
			len += SlReadUint16();
 
			_sl.obj_len = len;
 
			endoffs = _sl.reader->GetSize() + len;
 
			size_t start_pos = _sl.reader->GetSize();
 
			size_t endoffs = start_pos + len;
 
			ch.LoadCheck(len);
 
			if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size");
 

	
 
			if (_sl.reader->GetSize() != endoffs) {
 
				SlErrorCorruptFmt("Invalid chunk size in RIFF in {} - expected {}, got {}", ch.GetName(), len, _sl.reader->GetSize() - start_pos);
 
			}
 
			break;
 
		}
 
		default:
 
			SlErrorCorrupt("Invalid chunk type");
 
			break;
 
	}
 

	
 
	if (_sl.expect_table_header) SlErrorCorrupt("Table chunk without header");
0 comments (0 inline, 0 general)