[Scummvm-git-logs] scummvm master -> a3c3a22c422b9baeb6fdfaaba4a1f5dc788758a0

neuromancer noreply at scummvm.org
Mon Jun 29 08:19:55 UTC 2026


This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
7131be79f2 SCUMM: RA2: avoid a potential memory corruption (CID 1660738)
af32cea4c9 SCUMM: RA2: avoid a potential integer overflow (CID 1660810)
2fbf4fdc98 SCUMM: RA2: fixed an uninitilized variable (CID 1660805)
eeda392320 SCUMM: RA2: added missing fork in the L7
efd3fe7f90 FREESCAPE: fixed potential oob memory access
fcab8348c3 FREESCAPE: fixed integer truncation (CID 1645205)
48399626a7 COLONY: fixed potential oob read (CID 1653437)
2983124637 COLONY: fixed potential oob read (CID 1653428)
8dd6e6f9fb EEM: fixed potential oob read (CID 1660808)
a3c3a22c42 EEM: fixed potential oob read (CID 1660817)


Commit: 7131be79f2f3227f85675fc4d2411f83e148315a
    https://github.com/scummvm/scummvm/commit/7131be79f2f3227f85675fc4d2411f83e148315a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:35+02:00

Commit Message:
SCUMM: RA2: avoid a potential memory corruption (CID 1660738)

Changed paths:
    engines/scumm/insane/rebel2/iact.cpp


diff --git a/engines/scumm/insane/rebel2/iact.cpp b/engines/scumm/insane/rebel2/iact.cpp
index 3e9b985f83e..a6e5c212e38 100644
--- a/engines/scumm/insane/rebel2/iact.cpp
+++ b/engines/scumm/insane/rebel2/iact.cpp
@@ -2078,12 +2078,17 @@ void InsaneRebel2::iactRebel2Opcode9(byte *renderBitmap, Common::SeekableReadStr
 		if (ch == '^' && i + 1 < srcLen) {
 			byte next = (byte)textStr[i + 1];
 			if (next == 'f' && i + 3 < srcLen) {
+				// Reserve room for the escape bytes plus the terminating NUL.
+				if (dstIdx + 4 > (int)sizeof(convertedText) - 1)
+					break;
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i];
 				continue;
 			} else if (next == 'c' && i + 4 < srcLen) {
+				if (dstIdx + 5 > (int)sizeof(convertedText) - 1)
+					break;
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i++];
@@ -2091,6 +2096,8 @@ void InsaneRebel2::iactRebel2Opcode9(byte *renderBitmap, Common::SeekableReadStr
 				convertedText[dstIdx++] = textStr[i];
 				continue;
 			} else if (next == 'l') {
+				if (dstIdx + 2 > (int)sizeof(convertedText) - 1)
+					break;
 				convertedText[dstIdx++] = textStr[i++];
 				convertedText[dstIdx++] = textStr[i];
 				continue;


Commit: af32cea4c9a7a7790911389d649fc86202d909cb
    https://github.com/scummvm/scummvm/commit/af32cea4c9a7a7790911389d649fc86202d909cb
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:35+02:00

Commit Message:
SCUMM: RA2: avoid a potential integer overflow (CID 1660810)

Changed paths:
    engines/scumm/smush/rebel/font_rebel2.cpp


diff --git a/engines/scumm/smush/rebel/font_rebel2.cpp b/engines/scumm/smush/rebel/font_rebel2.cpp
index 97b5f29136f..77f2733eeaf 100644
--- a/engines/scumm/smush/rebel/font_rebel2.cpp
+++ b/engines/scumm/smush/rebel/font_rebel2.cpp
@@ -365,7 +365,12 @@ void Rebel2NutRenderer::loadRebel2Font(const char *filename) {
 		offset = (uint32)nextOffset;
 		int width = READ_LE_UINT16(dataSrc + offset + 14);
 		_fontHeight = READ_LE_UINT16(dataSrc + offset + 16);
-		decodedLength += width * _fontHeight;
+		const uint64 pixels = (uint64)width * _fontHeight;
+		if (pixels > kRebel2MaxSpritePixels || decodedLength + pixels > kRebel2MaxDecodedSpriteBytes) {
+			warning("Rebel2NutRenderer::loadRebel2Font(%s) invalid glyph dimensions %dx%d at char %d, clamping", filename, width, _fontHeight, l);
+			break;
+		}
+		decodedLength += (uint32)pixels;
 	}
 
 	if (l < _numChars)
@@ -413,9 +418,10 @@ void Rebel2NutRenderer::loadRebel2Font(const char *filename) {
 		_chars[l].height = READ_LE_UINT16(dataSrc + offset + 16);
 		_chars[l].src = decodedPtr;
 
-		decodedPtr += (_chars[l].width * _chars[l].height);
+		const uint32 pixels = (uint32)_chars[l].width * _chars[l].height;
+		decodedPtr += pixels;
 
-		memset(_chars[l].src, kDefaultTransparentColor, _chars[l].width * _chars[l].height);
+		memset(_chars[l].src, kDefaultTransparentColor, pixels);
 		_chars[l].transparency = kDefaultTransparentColor;
 
 		const uint8 *fobjptr = dataSrc + offset + 22;


Commit: 2fbf4fdc98abafd0b3e228751d141c177b71e6e0
    https://github.com/scummvm/scummvm/commit/2fbf4fdc98abafd0b3e228751d141c177b71e6e0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:35+02:00

Commit Message:
SCUMM: RA2: fixed an uninitilized variable (CID 1660805)

Changed paths:
    engines/scumm/insane/rebel2/iact.cpp


diff --git a/engines/scumm/insane/rebel2/iact.cpp b/engines/scumm/insane/rebel2/iact.cpp
index a6e5c212e38..3e4eef11df8 100644
--- a/engines/scumm/insane/rebel2/iact.cpp
+++ b/engines/scumm/insane/rebel2/iact.cpp
@@ -2190,6 +2190,7 @@ void InsaneRebel2::initEnemyStruct(int id, int32 x, int32 y, int32 w, int32 h, b
 	e.active = active;
 	e.destroyed = destroyed;
 	e.explosionFrame = explosionFrame;
+	e.explosionComplete = false;
 	e.savedBackground = nullptr;
 	e.savedBgWidth = 0;
 	e.savedBgHeight = 0;


Commit: eeda392320acb3ff45eba21cc84578f53c2e44e8
    https://github.com/scummvm/scummvm/commit/eeda392320acb3ff45eba21cc84578f53c2e44e8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
SCUMM: RA2: added missing fork in the L7

Changed paths:
    engines/scumm/insane/rebel2/rebel.cpp
    engines/scumm/insane/rebel2/rebel.h
    engines/scumm/insane/rebel2/render.cpp
    engines/scumm/insane/rebel2/runlevels.cpp


diff --git a/engines/scumm/insane/rebel2/rebel.cpp b/engines/scumm/insane/rebel2/rebel.cpp
index 9ce4d44b269..3903f0b3f04 100644
--- a/engines/scumm/insane/rebel2/rebel.cpp
+++ b/engines/scumm/insane/rebel2/rebel.cpp
@@ -439,6 +439,8 @@ InsaneRebel2::InsaneRebel2(ScummEngine_v7 *scumm) {
 	_flyOverlayRepeatCount = 0;
 	_flyShipScreenX = 0xd4;
 	_flyShipScreenY = 0x82;
+	_level7ForkActive = false;
+	_level7TookRightFork = false;
 	_smoothedVelocity = 0;
 	_verticalInput = 0;
 	memset(_velocityHistory, 0, sizeof(_velocityHistory));
diff --git a/engines/scumm/insane/rebel2/rebel.h b/engines/scumm/insane/rebel2/rebel.h
index 804f06b2c00..f4ccbf1b8d1 100644
--- a/engines/scumm/insane/rebel2/rebel.h
+++ b/engines/scumm/insane/rebel2/rebel.h
@@ -639,6 +639,7 @@ public:
 	void checkHandler7RightBoundary(const CollisionZone &zone, int16 hMargin, int wallDamage);
 	void checkHandler7BoundaryZones(uint16 &warningMask);
 	void renderHandler7WarningCues(byte *renderBitmap, int pitch, int width, int height, int32 curFrame, uint16 warningMask);
+	void updateLevel7Fork(int32 curFrame);
 
 	int16 _playerDamage;
 	int16 _playerShield;
@@ -816,6 +817,10 @@ public:
 	int16 _flyShipScreenX;
 	int16 _flyShipScreenY;
 
+	// Level 7 (handler-7 flight) corridor fork: 07PLAY -> 07PLAYB right branch.
+	bool _level7ForkActive;     // armed only while 07PLAY is playing
+	bool _level7TookRightFork;  // sampled at frame 0x638: ship on the right half
+
 	int16 _smoothedVelocity;
 	int16 _verticalInput;
 	int16 _velocityHistory[25];
diff --git a/engines/scumm/insane/rebel2/render.cpp b/engines/scumm/insane/rebel2/render.cpp
index 5f4af086950..ddaa6bf2aa6 100644
--- a/engines/scumm/insane/rebel2/render.cpp
+++ b/engines/scumm/insane/rebel2/render.cpp
@@ -2110,6 +2110,22 @@ void InsaneRebel2::updatePostRenderDeath() {
 	}
 }
 
+void InsaneRebel2::updateLevel7Fork(int32 curFrame) {
+	// Level 7 (TIE-fighter flight) forks at frame 0x638: if the ship is on the
+	// right half of the corridor (_flyShipScreenX past the 0xd4 center, matching
+	// the original's DAT_0047ab8c test), stop 07PLAY here so the alternate
+	// 07PLAYB segment can splice in. The left half plays 07PLAY through to its
+	// end. Sampled exactly once (the active flag is its own one-shot guard).
+	if (!_level7ForkActive || curFrame < 0x638)
+		return;
+
+	_level7ForkActive = false;
+	if (_flyShipScreenX > 0xd4) {
+		_level7TookRightFork = true;
+		_vm->_smushVideoShouldFinish = true;
+	}
+}
+
 void InsaneRebel2::renderPostRenderMenuCursor(byte *renderBitmap, int pitch, int width, int height) {
 	static const byte kRa2MenuCursor[] = {
 		 0,  0,  1,  1,  1,  1,  1,
@@ -2390,6 +2406,7 @@ void InsaneRebel2::procPostRendering(byte *renderBitmap, int32 codecparam, int32
 
 	updatePostRenderScroll(width, height);
 	updatePostRenderDeath();
+	updateLevel7Fork(curFrame);
 
 	// End the looping attack-run segment once the shield/reactor is destroyed.
 	if (_rebelShieldGateActive) {
diff --git a/engines/scumm/insane/rebel2/runlevels.cpp b/engines/scumm/insane/rebel2/runlevels.cpp
index 2fa6af8f705..e6aaec7d7a6 100644
--- a/engines/scumm/insane/rebel2/runlevels.cpp
+++ b/engines/scumm/insane/rebel2/runlevels.cpp
@@ -887,8 +887,6 @@ int InsaneRebel2::runLevel6() {
 }
 
 int InsaneRebel2::runLevel7() {
-	bool reachedFork = false;
-
 	playCinematic("LEV07/07CUT.SAN");
 	if (_vm->shouldQuit())
 		return kLevelQuit;
@@ -903,25 +901,43 @@ int InsaneRebel2::runLevel7() {
 		_playerShield = 255;
 		_playerDamage = 0;
 		_deathFrame = 0;
-		reachedFork = false;
+		_level7TookRightFork = false;
 		resetExplosions();
 
 		clearBit(0);
 		_rebelKillCounter = 0;
 		_rebelHitCounter = 0;
 
-		if (!playLevelSegment("LEV07/07PLAY.SAN", 0x28))
+		// The corridor forks at frame 0x638. updateLevel7Fork() is armed only
+		// during 07PLAY: if the player is on the right half there, it stops this
+		// segment (so 07PLAYB can splice in) and sets _level7TookRightFork; the
+		// left half plays 07PLAY through to its end.
+		_level7ForkActive = true;
+		const bool playOk = playLevelSegment("LEV07/07PLAY.SAN", 0x28);
+		_level7ForkActive = false;
+		if (!playOk)
 			return kLevelQuit;
 
+		// Right fork: continue into the alternate corridor segment (0x40 =
+		// continuation, so the ship position carries over instead of recentering).
+		if (_level7TookRightFork && _playerShield > 0) {
+			if (!playLevelSegment("LEV07/07PLAYB.SAN", 0x68))
+				return kLevelQuit;
+		}
+
 		if (_playerShield > 0) {
-			debugC(DEBUG_INSANE, "Level 7 completed!");
-			playLevelEnd(7, -1, _rebelHitCounter, !reachedFork);
+			debugC(DEBUG_INSANE, "Level 7 completed! fork=%d", _level7TookRightFork);
+			playLevelEnd(7, -1, _rebelHitCounter, !_level7TookRightFork);
 			_levelUnlocked[7] = true;
 			return kLevelNextLevel;
 		}
 
-		debugC(DEBUG_INSANE, "Level 7 death at frame %d, fork=%d", _deathFrame, reachedFork);
-		if (reachedFork) {
+		// Death cinematic depends on which corridor side the player died on
+		// (the original keys 07DIE_B/07DIE_A on DAT_0047ab8c), independent of
+		// the fork frame; taking the right fork implies the right side.
+		const bool diedOnRight = _level7TookRightFork || (_flyShipScreenX > 0xd4);
+		debugC(DEBUG_INSANE, "Level 7 death at frame %d, right=%d", _deathFrame, diedOnRight);
+		if (diedOnRight) {
 			playCinematic("LEV07/07DIE_B.SAN");
 		} else {
 			playCinematic("LEV07/07DIE_A.SAN");


Commit: efd3fe7f903ae99b1a164581ecd4b6a1acdb7b69
    https://github.com/scummvm/scummvm/commit/efd3fe7f903ae99b1a164581ecd4b6a1acdb7b69
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
FREESCAPE: fixed potential oob memory access

Changed paths:
    engines/freescape/unpack.cpp


diff --git a/engines/freescape/unpack.cpp b/engines/freescape/unpack.cpp
index 31c177e8bbb..c22dd7cbeee 100644
--- a/engines/freescape/unpack.cpp
+++ b/engines/freescape/unpack.cpp
@@ -190,14 +190,15 @@ unsigned char *create_reloc_table(struct memstream *ms, struct dos_header *dh, s
 			if (msread(ms, &entry, sizeof(unsigned short)) != sizeof(unsigned short)) {
 				debug("msread failed");
 			}
-			if (reloc_position >= *reloc_table_size) {
-				debug("overflow");
+			// The relocation counts are read from the (untrusted) packed file,
+			// so their sum can exceed the header-derived table size. Stop before
+			// writing past the end of buf_reloc rather than overflowing it.
+			if (reloc_position + 2 * sizeof(unsigned short) > *reloc_table_size) {
+				debug("relocation table overflow, truncating");
+				break;
 			}
 			*(unsigned short*)(buf_reloc + reloc_position) = entry;
 			reloc_position += 2;
-			if (reloc_position >= *reloc_table_size) {
-				debug("overflow");
-			}
 			*(unsigned short*)(buf_reloc + reloc_position) = (i * 0x1000) & 0xFFFF;
 			reloc_position += 2;
 		}


Commit: fcab8348c3e2da5662fae2155ad7da597606df53
    https://github.com/scummvm/scummvm/commit/fcab8348c3e2da5662fae2155ad7da597606df53
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
FREESCAPE: fixed integer truncation (CID 1645205)

Changed paths:
    engines/freescape/sound/amiga.cpp


diff --git a/engines/freescape/sound/amiga.cpp b/engines/freescape/sound/amiga.cpp
index 463c8ecb556..ee104b6b27b 100644
--- a/engines/freescape/sound/amiga.cpp
+++ b/engines/freescape/sound/amiga.cpp
@@ -309,7 +309,7 @@ private:
 								}
 							}
 
-						double durationSec = (dmaCount + 1) * bufSize * _periodShadow[0] / Audio::Paula::kPalPaulaClock;
+						double durationSec = (double)(dmaCount + 1) * bufSize * _periodShadow[0] / Audio::Paula::kPalPaulaClock;
 						_dmaCounter = (int)(durationSec * 50.0) + 1;
 						_dmaAud0Active = true;
 						enableChannel(0);


Commit: 48399626a770be425cece978947ed065fb40d67e
    https://github.com/scummvm/scummvm/commit/48399626a770be425cece978947ed065fb40d67e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
COLONY: fixed potential oob read (CID 1653437)

Changed paths:
    engines/colony/interaction.cpp


diff --git a/engines/colony/interaction.cpp b/engines/colony/interaction.cpp
index 57709656628..bd6ad01bd42 100644
--- a/engines/colony/interaction.cpp
+++ b/engines/colony/interaction.cpp
@@ -136,7 +136,7 @@ void ColonyEngine::interactWithObject(int objNum) {
 					_carryPatch[1].xloc = 1;
 					_carryPatch[1].yloc = 1;
 					_carryPatch[1].ang = 1;
-					newPatch(kObjTeleport, from, _carryPatch[1], _mapData[from.xindex][from.yindex][4]);
+					newPatch(kObjTeleport, from, _carryPatch[1], _mapData[CLIP<int>(from.xindex, 0, 30)][CLIP<int>(from.yindex, 0, 30)][4]);
 					_carryType = kObjTeleport;
 					_robotArray[obj.where.xindex][obj.where.yindex] = 0;
 					_objects[objNum - 1].alive = 0;
@@ -230,7 +230,7 @@ void ColonyEngine::interactWithObject(int objNum) {
 					_carryPatch[0].xloc = 0;
 					_carryPatch[0].yloc = 0;
 					_carryPatch[0].ang = 0;
-					newPatch(kObjForkLift, from, _carryPatch[0], _mapData[from.xindex][from.yindex][4]);
+					newPatch(kObjForkLift, from, _carryPatch[0], _mapData[CLIP<int>(from.xindex, 0, 30)][CLIP<int>(from.yindex, 0, 30)][4]);
 					_robotArray[obj.where.xindex][obj.where.yindex] = 0;
 					_objects[objNum - 1].alive = 0;
 					_me.look = _me.ang = obj.where.ang;
@@ -263,7 +263,7 @@ void ColonyEngine::interactWithObject(int objNum) {
 					_carryPatch[1].xloc = 1;
 					_carryPatch[1].yloc = 1;
 					_carryPatch[1].ang = 1;
-					newPatch(obj.type, from, _carryPatch[1], _mapData[from.xindex][from.yindex][4]);
+					newPatch(obj.type, from, _carryPatch[1], _mapData[CLIP<int>(from.xindex, 0, 30)][CLIP<int>(from.yindex, 0, 30)][4]);
 					_carryType = obj.type;
 					_robotArray[obj.where.xindex][obj.where.yindex] = 0;
 					_objects[objNum - 1].alive = 0;


Commit: 29831246374ca836391e94db700f53c74cb2a5ad
    https://github.com/scummvm/scummvm/commit/29831246374ca836391e94db700f53c74cb2a5ad
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
COLONY: fixed potential oob read (CID 1653428)

Changed paths:
    engines/colony/think.cpp


diff --git a/engines/colony/think.cpp b/engines/colony/think.cpp
index 3c4233c0637..c7f75a1b038 100644
--- a/engines/colony/think.cpp
+++ b/engines/colony/think.cpp
@@ -586,7 +586,10 @@ void ColonyEngine::snoopThink(int num) {
 	}
 
 	case kOpcodeSnoop: {
-		const int target = trailTargetAngle(_dirXY[obj.where.xindex][obj.where.yindex]);
+		int target = -1;
+		if (obj.where.xindex >= 0 && obj.where.xindex < 32 &&
+			obj.where.yindex >= 0 && obj.where.yindex < 32)
+			target = trailTargetAngle(_dirXY[obj.where.xindex][obj.where.yindex]);
 		if (target >= 0 && obj.where.ang != target) {
 			const int diff = (target - obj.where.ang) & 0xFF;
 			if (diff < 128)


Commit: 8dd6e6f9fb51ed3b0756a3ea5b8624a7791a6f47
    https://github.com/scummvm/scummvm/commit/8dd6e6f9fb51ed3b0756a3ea5b8624a7791a6f47
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
EEM: fixed potential oob read (CID 1660808)

Changed paths:
    engines/eem/mystery.cpp


diff --git a/engines/eem/mystery.cpp b/engines/eem/mystery.cpp
index 2d54b907286..f385635d29d 100644
--- a/engines/eem/mystery.cpp
+++ b/engines/eem/mystery.cpp
@@ -439,6 +439,8 @@ bool Mystery::load(uint num, Common::RandomSource *rng, bool macintosh) {
 		const byte *susSec   = (_floppyGalleryOff < _data.size())
 								? _data.data() + _floppyGalleryOff : nullptr;
 		_numSites    = sitesSec ? *sitesSec : 0;
+		if (_numSites > kVisitedSiteCap)
+			_numSites = kVisitedSiteCap;
 		_numSuspects = susSec   ? *susSec   : 0;
 		_numCONSITEs = 0;
 		_numCOFFSITEs = 0;


Commit: a3c3a22c422b9baeb6fdfaaba4a1f5dc788758a0
    https://github.com/scummvm/scummvm/commit/a3c3a22c422b9baeb6fdfaaba4a1f5dc788758a0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-29T10:15:36+02:00

Commit Message:
EEM: fixed potential oob read (CID 1660817)

Changed paths:
    engines/eem/graphics.cpp


diff --git a/engines/eem/graphics.cpp b/engines/eem/graphics.cpp
index 343653921a1..f283765f3cd 100644
--- a/engines/eem/graphics.cpp
+++ b/engines/eem/graphics.cpp
@@ -490,6 +490,10 @@ void EEMEngine::doHelp() {
 			return;
 		}
 		const uint32 hsz = hf.size();
+		// An empty help file leaves hbuf.data() null below; bail before the
+		// hd[0] read so it cannot dereference null.
+		if (hsz == 0)
+			return;
 		Common::Array<byte> hbuf;
 		hbuf.resize(hsz);
 		if (hf.read(hbuf.data(), hsz) != hsz)




More information about the Scummvm-git-logs mailing list