aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/unpack.cpp
diff options
context:
space:
mode:
authorKari Salminen2008-06-13 05:57:07 +0000
committerKari Salminen2008-06-13 05:57:07 +0000
commitd7d9348243ea203c88a5798c2cbbc70c0ee93ba4 (patch)
tree660ae4f7d7a937d8ceed927373b7cb074b452fe9 /engines/cine/unpack.cpp
parent46681407ab8788461546af1bda99b9c3c7859ffa (diff)
downloadscummvm-rg350-d7d9348243ea203c88a5798c2cbbc70c0ee93ba4.tar.gz
scummvm-rg350-d7d9348243ea203c88a5798c2cbbc70c0ee93ba4.tar.bz2
scummvm-rg350-d7d9348243ea203c88a5798c2cbbc70c0ee93ba4.zip
Made CineUnpacker::unpack more robust & secure. It shouldn't crash now with any input (Before making reading or writing operations they are checked to be in bounds). Also updated some comments and added some error message(s).
svn-id: r32687
Diffstat (limited to 'engines/cine/unpack.cpp')
-rw-r--r--engines/cine/unpack.cpp37
1 files changed, 28 insertions, 9 deletions
diff --git a/engines/cine/unpack.cpp b/engines/cine/unpack.cpp
index 364331e439..a27387a1e3 100644
--- a/engines/cine/unpack.cpp
+++ b/engines/cine/unpack.cpp
@@ -31,6 +31,10 @@
namespace Cine {
uint32 CineUnpacker::readSource() {
+ if (_src < _srcBegin || _src + 4 > _srcEnd) {
+ _error = true;
+ return 0; // The source pointer is out of bounds, returning a default value
+ }
uint32 value = READ_BE_UINT32(_src);
_src -= 4;
return value;
@@ -67,7 +71,10 @@ uint16 CineUnpacker::getBits(byte numBits) {
}
void CineUnpacker::unpackRawBytes(uint16 numBytes) {
- _datasize -= numBytes;
+ if (_dst >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
+ _error = true;
+ return; // Destination pointer is out of bounds for this operation
+ }
while (numBytes--) {
*_dst = (byte)getBits(8);
--_dst;
@@ -75,21 +82,33 @@ void CineUnpacker::unpackRawBytes(uint16 numBytes) {
}
void CineUnpacker::copyRelocatedBytes(uint16 offset, uint16 numBytes) {
- _datasize -= numBytes;
+ if (_dst + offset >= _dstEnd || _dst - numBytes + 1 < _dstBegin) {
+ _error = true;
+ return; // Destination pointer is out of bounds for this operation
+ }
while (numBytes--) {
*_dst = *(_dst + offset);
--_dst;
}
}
-bool CineUnpacker::unpack(byte *dst, const byte *src, int srcLen) {
- _src = src + srcLen - 4;
- _datasize = readSource(); // Unpacked length in bytes
- _dst = dst + _datasize - 1;
+bool CineUnpacker::unpack(const byte *src, uint srcLen, byte *dst, uint dstLen) {
+ // Initialize variables used for detecting errors during unpacking
+ _error = false;
+ _srcBegin = src;
+ _srcEnd = src + srcLen;
+ _dstBegin = dst;
+ _dstEnd = dst + dstLen;
+
+ // Initialize other variables
+ _src = _srcBegin + srcLen - 4;
+ uint32 unpackedLength = readSource(); // Unpacked length in bytes
+ _dst = _dstBegin + unpackedLength - 1;
_crc = readSource();
_chunk32b = readSource();
_crc ^= _chunk32b;
- do {
+
+ while (_dst >= _dstBegin && !_error) {
/*
Bits => Action:
0 0 => unpackRawBytes(3 bits + 1) i.e. unpackRawBytes(1..9)
@@ -123,8 +142,8 @@ bool CineUnpacker::unpack(byte *dst, const byte *src, int srcLen) {
copyRelocatedBytes(offset, numBytes);
}
}
- } while (_datasize > 0 && _src >= src - 4);
- return _crc == 0;
+ }
+ return !_error && (_crc == 0);
}
} // End of namespace Cine