Changeset - r14339:de4085d8bcf9
[Not reviewed]
master
0 1 0
michi_cc - 15 years ago 2010-01-23 22:23:45
michi_cc@openttd.org
(svn r18904) -Fix: Writing LZO-compressed savegames would produce invalid files and potentially overwrite memory.
1 file changed with 16 insertions and 6 deletions:
0 comments (0 inline, 0 general)
src/saveload/saveload.cpp
Show inline comments
 
@@ -1243,25 +1243,26 @@ static void SlFixPointers()
 
/*******************************************
 
 ********** START OF LZO CODE **************
 
 *******************************************/
 

	
 
#ifdef WITH_LZO
 
#include <lzo/lzo1x.h>
 

	
 
/** Buffer size for the LZO compressor */
 
static const uint LZO_BUFFER_SIZE = 8192;
 

	
 
static size_t ReadLZO()
 
{
 
	byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 64 + 16 + 3 + 8];
 
	/* Buffer size is from the LZO docs plus the chunk header size. */
 
	byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
 
	uint32 tmp[2];
 
	uint32 size;
 
	lzo_uint len;
 

	
 
	/* Read header*/
 
	if (fread(tmp, sizeof(tmp), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE, "File read failed");
 

	
 
	/* Check if size is bad */
 
	((uint32*)out)[0] = size = tmp[1];
 

	
 
	if (_sl_version != 0) {
 
		tmp[0] = TO_BE32(tmp[0]);
 
@@ -1272,40 +1273,49 @@ static size_t ReadLZO()
 

	
 
	/* Read block */
 
	if (fread(out + sizeof(uint32), size, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
 

	
 
	/* Verify checksum */
 
	if (tmp[0] != lzo_adler32(0, out, size + sizeof(uint32))) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, "Bad checksum");
 

	
 
	/* Decompress */
 
	lzo1x_decompress(out + sizeof(uint32) * 1, size, _sl.buf, &len, NULL);
 
	return len;
 
}
 

	
 
/* p contains the pointer to the buffer, len contains the pointer to the length.
 
 * len bytes will be written, p and l will be updated to reflect the next buffer. */
 
static void WriteLZO(size_t size)
 
{
 
	byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 64 + 16 + 3 + 8];
 
	byte wrkmem[sizeof(byte*) * 4096];
 
	const lzo_bytep in = _sl.buf;
 
	/* Buffer size is from the LZO docs plus the chunk header size. */
 
	byte out[LZO_BUFFER_SIZE + LZO_BUFFER_SIZE / 16 + 64 + 3 + sizeof(uint32) * 2];
 
	byte wrkmem[LZO1X_1_MEM_COMPRESS];
 
	lzo_uint outlen;
 

	
 
	lzo1x_1_compress(_sl.buf, (lzo_uint)size, out + sizeof(uint32) * 2, &outlen, wrkmem);
 
	do {
 
		/* Compress up to LZO_BUFFER_SIZE bytes at once. */
 
		lzo_uint len = size > LZO_BUFFER_SIZE ? LZO_BUFFER_SIZE : (lzo_uint)size;
 
		lzo1x_1_compress(in, len, out + sizeof(uint32) * 2, &outlen, wrkmem);
 
	((uint32*)out)[1] = TO_BE32((uint32)outlen);
 
	((uint32*)out)[0] = TO_BE32(lzo_adler32(0, out + sizeof(uint32), outlen + sizeof(uint32)));
 
	if (fwrite(out, outlen + sizeof(uint32) * 2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
 

	
 
		/* Move to next data chunk. */
 
		size -= len;
 
		in += len;
 
	} while (size > 0);
 
}
 

	
 
static bool InitLZO(byte compression)
 
{
 
	if (lzo_init() != LZO_E_OK) return false;
 
	_sl.bufsize = LZO_BUFFER_SIZE;
 
	_sl.buf = _sl.buf_ori = MallocT<byte>(LZO_BUFFER_SIZE);
 
	return true;
 
}
 

	
 
static void UninitLZO()
 
{
 
	free(_sl.buf_ori);
 
}
 

	
 
#endif /* WITH_LZO */
 

	
0 comments (0 inline, 0 general)