[Scummvm-cvs-logs] SF.net SVN: scummvm:[55258] scummvm/trunk/graphics/video
drmccoy at users.sourceforge.net
drmccoy at users.sourceforge.net
Sun Jan 16 17:27:22 CET 2011
Revision: 55258
http://scummvm.svn.sourceforge.net/scummvm/?rev=55258&view=rev
Author: drmccoy
Date: 2011-01-16 16:27:22 +0000 (Sun, 16 Jan 2011)
Log Message:
-----------
VIDEO: Add range checks to deLZ77()
Modified Paths:
--------------
scummvm/trunk/graphics/video/coktel_decoder.cpp
scummvm/trunk/graphics/video/coktel_decoder.h
Modified: scummvm/trunk/graphics/video/coktel_decoder.cpp
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.cpp 2011-01-16 16:26:52 UTC (rev 55257)
+++ scummvm/trunk/graphics/video/coktel_decoder.cpp 2011-01-16 16:27:22 UTC (rev 55258)
@@ -268,64 +268,83 @@
return (_features & kFeaturesPalette) && _paletteDirty;
}
-void CoktelDecoder::deLZ77(byte *dest, byte *src) {
- int i;
- byte buf[4370];
- uint16 chunkLength;
- uint32 frameLength;
+uint32 CoktelDecoder::deLZ77(byte *dest, const byte *src, uint32 srcSize, uint32 destSize) {
+ uint32 frameLength = READ_LE_UINT32(src);
+ if (frameLength > destSize) {
+ warning("CoktelDecoder::deLZ77(): Uncompressed size bigger than buffer size (%d > %d)", frameLength, destSize);
+ return 0;
+ }
+
+ assert(srcSize >= 4);
+
+ uint32 realSize = frameLength;
+
+ src += 4;
+ srcSize -= 4;
+
uint16 bufPos1;
- uint16 bufPos2;
- uint16 tmp;
- uint8 chunkBitField;
- uint8 chunkCount;
bool mode;
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ assert(srcSize >= 4);
- frameLength = READ_LE_UINT32(src);
- src += 4;
+ src += 4;
+ srcSize -= 4;
- if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
- src += 4;
bufPos1 = 273;
- mode = 1; // 123Ch (cmp al, 12h)
+ mode = 1; // 123Ch (cmp al, 12h)
} else {
bufPos1 = 4078;
- mode = 0; // 275h (jnz +2)
+ mode = 0; // 275h (jnz +2)
}
+ byte buf[4370];
memset(buf, 32, bufPos1);
- chunkCount = 1;
- chunkBitField = 0;
+ uint8 chunkCount = 1;
+ uint8 chunkBitField = 0;
+
while (frameLength > 0) {
chunkCount--;
+
if (chunkCount == 0) {
- tmp = *src++;
- chunkCount = 8;
- chunkBitField = tmp;
+ chunkCount = 8;
+ chunkBitField = *src++;
}
+
if (chunkBitField % 2) {
+ assert(srcSize >= 1);
+
chunkBitField >>= 1;
buf[bufPos1] = *src;
*dest++ = *src++;
bufPos1 = (bufPos1 + 1) % 4096;
frameLength--;
+ srcSize--;
continue;
}
chunkBitField >>= 1;
- tmp = READ_LE_UINT16(src);
- src += 2;
- chunkLength = ((tmp & 0xF00) >> 8) + 3;
+ assert(srcSize >= 2);
+ uint16 tmp = READ_LE_UINT16(src);
+ uint16 chunkLength = ((tmp & 0xF00) >> 8) + 3;
+
+ src += 2;
+ srcSize -= 2;
+
if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
- (!mode && (chunkLength == 0)))
+ (!mode && (chunkLength == 0))) {
+ assert(srcSize >= 1);
+
chunkLength = *src++ + 0x12;
+ srcSize--;
+ }
- bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
+ uint16 bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
if (((tmp + chunkLength) >= 4096) ||
((chunkLength + bufPos1) >= 4096)) {
- for (i = 0; i < chunkLength; i++, dest++) {
+ for (int i = 0; i < chunkLength; i++, dest++) {
*dest = buf[bufPos2];
buf[bufPos1] = buf[bufPos2];
bufPos1 = (bufPos1 + 1) % 4096;
@@ -338,13 +357,13 @@
memcpy(dest, buf + bufPos2, chunkLength);
memmove(buf + bufPos1, buf + bufPos2, chunkLength);
- dest += chunkLength;
+ dest += chunkLength;
bufPos1 += chunkLength;
bufPos2 += chunkLength;
} else {
- for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ for (int i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
*dest = buf[bufPos2];
buf[bufPos1] = buf[bufPos2];
}
@@ -353,6 +372,8 @@
frameLength -= chunkLength;
}
+
+ return realSize;
}
void CoktelDecoder::deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen) {
@@ -1316,7 +1337,8 @@
// Result is empty => nothing to do
return false;
- byte *dataPtr = _videoBuffer[0];
+ byte *dataPtr = _videoBuffer[0];
+ uint32 dataSize = _videoBufferLen[0] - 1;
uint8 type = *dataPtr++;
@@ -1330,7 +1352,8 @@
for (int i = 0; i < count; i++)
_palette[index * 3 + i] = dataPtr[i] << 2;
- dataPtr += 48;
+ dataPtr += 48;
+ dataSize -= 49;
type ^= 0x10;
_paletteDirty = true;
@@ -1343,13 +1366,15 @@
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
// Directly uncompress onto the video surface
- deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
+ deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr, dataSize,
+ _surface.w * _surface.h * _surface.bytesPerPixel);
return true;
}
- deLZ77(_videoBuffer[1], dataPtr);
+ _videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
- dataPtr = _videoBuffer[1];
+ dataPtr = _videoBuffer[1];
+ dataSize = _videoBufferLen[1];
}
// Evaluate the block type
@@ -2133,7 +2158,8 @@
return false;
}
- byte *dataPtr = _videoBuffer[0];
+ byte *dataPtr = _videoBuffer[0];
+ uint32 dataSize = _videoBufferLen[0] - 1;
uint8 type = *dataPtr++;
@@ -2144,13 +2170,15 @@
if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
// Directly uncompress onto the video surface
- deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr);
+ deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr, dataSize,
+ _surface.w * _surface.h * _surface.bytesPerPixel);
return true;
}
- deLZ77(_videoBuffer[1], dataPtr);
+ _videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
- dataPtr = _videoBuffer[1];
+ dataPtr = _videoBuffer[1];
+ dataSize = _videoBufferLen[1];
}
// Evaluate the block type
Modified: scummvm/trunk/graphics/video/coktel_decoder.h
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.h 2011-01-16 16:26:52 UTC (rev 55257)
+++ scummvm/trunk/graphics/video/coktel_decoder.h 2011-01-16 16:27:22 UTC (rev 55258)
@@ -191,7 +191,7 @@
void freeSurface();
// Decompression
- void deLZ77(byte *dest, byte *src);
+ uint32 deLZ77(byte *dest, const byte *src, uint32 srcSize, uint32 destSize);
void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen);
// Block rendering
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list