[Scummvm-git-logs] scummvm master -> 164498f204ba60cf9089af16ccd6febbbd0d2d8d
elasota
noreply at scummvm.org
Wed Jan 3 03:34:23 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
164498f204 MTROPOLIS: Fix out-of-range read when loading 8-bit mToon assets
Commit: 164498f204ba60cf9089af16ccd6febbbd0d2d8d
https://github.com/scummvm/scummvm/commit/164498f204ba60cf9089af16ccd6febbbd0d2d8d
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-01-02T22:34:06-05:00
Commit Message:
MTROPOLIS: Fix out-of-range read when loading 8-bit mToon assets
Changed paths:
engines/mtropolis/assets.cpp
engines/mtropolis/assets.h
diff --git a/engines/mtropolis/assets.cpp b/engines/mtropolis/assets.cpp
index eb0e8bf3d57..64c28574580 100644
--- a/engines/mtropolis/assets.cpp
+++ b/engines/mtropolis/assets.cpp
@@ -314,6 +314,29 @@ bool CachedMToon::decompressMToonRLE(const RleFrame &frame, const Common::Array<
return true;
}
+template<class TDest, class TSrc>
+void CachedMToon::checkedMemCpy(Common::Array<TDest> &dest, size_t destIndex, const Common::Array<TSrc> &src, size_t srcIndex, size_t sizeBytes) {
+ if (sizeBytes == 0)
+ return;
+
+ size_t destSize = dest.size() * sizeof(TDest);
+ size_t srcSize = src.size() * sizeof(TSrc);
+
+ if (destIndex > dest.size() || srcIndex > src.size())
+ error("Out-of-range data copy offset while loading mToon");
+
+ size_t srcPos = srcIndex * sizeof(TSrc);
+ size_t destPos = destIndex * sizeof(TDest);
+
+ size_t srcAvail = srcSize - srcPos;
+ size_t destAvail = destSize - destPos;
+
+ if (srcAvail < sizeBytes || destAvail < sizeBytes)
+ error("Out-of-range data copy end while loading mToon");
+
+ memcpy(&dest[destIndex], &src[srcIndex], sizeBytes);
+}
+
void CachedMToon::decompressRLEFrameToImage(size_t frameIndex, Graphics::ManagedSurface &surface) {
assert(surface.format == _rleOptimizedFormat);
@@ -348,6 +371,9 @@ void CachedMToon::loadRLEFrames(const Common::Array<uint8> &data) {
size_t baseOffset = frameDef.dataOffset;
+ if (frameDef.compressedSize < 20)
+ error("Invalid compressed data size");
+
uint32 headerInts[5];
for (size_t hi = 0; hi < 5; hi++) {
uint32 unpacked = 0;
@@ -373,15 +399,15 @@ void CachedMToon::loadRLEFrames(const Common::Array<uint8> &data) {
uint32 frameDataSize = headerInts[4];
if (frameDataSize > 0) {
+ // frameDataSize is sometimes set to frameDef.compressedSize but sometimes contains garbage,
+ // so we need to ignore it and derive size from the frameDef instead.
if (bpp == 8) {
- rleFrame.data8.resize(frameDataSize);
- memcpy(&rleFrame.data8[0], &data[baseOffset + 20], frameDataSize);
+ rleFrame.data8.resize(frameDef.compressedSize - 20);
+ checkedMemCpy(rleFrame.data8, 0, data, baseOffset + 20, frameDef.compressedSize - 20);
} else if (bpp == 16) {
- // In RLE16, frameDataSize is sometimes set to frameDef.compressedSize but sometimes contains garbage,
- // so we need to ignore it and derive size from the frameDef instead.
uint32 numDWords = (frameDef.compressedSize - 20) / 2;
rleFrame.data16.resize(numDWords);
- memcpy(&rleFrame.data16[0], &data[baseOffset + 20], static_cast<size_t>(numDWords) * 2u);
+ checkedMemCpy(rleFrame.data16, 0, data, baseOffset + 20, static_cast<size_t>(numDWords) * 2u);
uint16 *i16 = &rleFrame.data16[0];
if (_metadata->imageFormat == MToonMetadata::kImageFormatWindows) {
diff --git a/engines/mtropolis/assets.h b/engines/mtropolis/assets.h
index f440199c2f2..1b809e30cf4 100644
--- a/engines/mtropolis/assets.h
+++ b/engines/mtropolis/assets.h
@@ -146,6 +146,9 @@ private:
template<class TNumber, uint32 TLiteralMask, uint32 TTransparentRowSkipMask>
static bool decompressMToonRLE(const RleFrame &frame, const Common::Array<TNumber> &coefsArray, Graphics::ManagedSurface &surface, bool isBottomUp, bool isKeyFrame, uint hackFlags);
+ template<class TDest, class TSrc>
+ static void checkedMemCpy(Common::Array<TDest> &dest, size_t destIndex, const Common::Array<TSrc> &src, size_t srcIndex, size_t sizeBytes);
+
Common::Array<RleFrame> _rleData;
bool _isRLETemporalCompressed;
More information about the Scummvm-git-logs
mailing list