[Scummvm-git-logs] scummvm master -> 0ad9953c49dab229ea86d290d808de97945414cf

fracturehill noreply at scummvm.org
Tue Nov 11 18:58:49 UTC 2025


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

Summary:
c6e7f52be8 NANCY: Fix buffer overread when saving puzzle data
3b555f1c6c NANCY: Fix overwrite dialog in nancy8 save menu
0ad9953c49 NANCY: Fix calling of phone numbers not in list


Commit: c6e7f52be8c49fb11bdf5034c22c3f644b063992
    https://github.com/scummvm/scummvm/commit/c6e7f52be8c49fb11bdf5034c22c3f644b063992
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2025-11-11T19:58:23+01:00

Commit Message:
NANCY: Fix buffer overread when saving puzzle data

RippedLetterPuzzleData was reading and writing
two arrays, expecting them to be of a fixed size.
However, the puzzle code actually replaces those arrays
when initializing, and this could potentially make the
arrays smaller than expected. The saving code would then
read past the end of those arrays.

This commit fixes the issue by forcibly resizing the
arrays to 24, and making sure that the code that
checks for the correct ordering in the puzzle does
not rely on the array being a certain size.

Changed paths:
    engines/nancy/action/puzzle/rippedletterpuzzle.cpp
    engines/nancy/puzzledata.cpp


diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
index 90a4d64b8f9..14c898f5b57 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.cpp
@@ -100,6 +100,8 @@ void RippedLetterPuzzle::readData(Common::SeekableReadStream &stream) {
 	uint elemSize = g_nancy->getGameType() <= kGameTypeNancy8 ? 1 : 2;
 
 	_initOrder.resize(width * height);
+	assert(width * height <= 24); // If this gets hit we need to increase the sizes in RippedLetterPuzzleData
+
 	for (uint i = 0; i < height; ++i) {
 		for (uint j = 0; j < width; ++j) {
 			_initOrder[i * width + j] = (elemSize == 1 ? stream.readByte() : stream.readSint16LE());
@@ -423,11 +425,7 @@ bool RippedLetterPuzzle::checkOrder(bool useAlt) {
 	auto &current = _puzzleState->order;
 	auto &correct = useAlt ? _solveOrderAlt : _solveOrder;
 
-	if (!_doubles.size()) {
-		return current == correct;
-	}
-
-	for (uint i = 0; i < current.size(); ++i) {
+	for (uint i = 0; i < correct.size(); ++i) {
 		bool foundCorrect = false;
 		bool isDoubled = false;
 		for (auto &d : _doubles) {
diff --git a/engines/nancy/puzzledata.cpp b/engines/nancy/puzzledata.cpp
index b17fe76a763..f7c28404960 100644
--- a/engines/nancy/puzzledata.cpp
+++ b/engines/nancy/puzzledata.cpp
@@ -58,22 +58,20 @@ RippedLetterPuzzleData::RippedLetterPuzzleData() :
 	playerHasTriedPuzzle(false) {}
 
 void RippedLetterPuzzleData::synchronize(Common::Serializer &ser) {
-	if (ser.isLoading()) {
-		order.resize(24);
-		rotations.resize(24);
-	} else {
-		// A piece may still be held while saving; make sure the saved data
-		// has it back in the last place it was picked up from
-		if (_pickedUpPieceID != -1) {
-			order[_pickedUpPieceLastPos] = _pickedUpPieceID;
-			rotations[_pickedUpPieceLastPos] = _pickedUpPieceRot;
-			_pickedUpPieceID = -1;
-			_pickedUpPieceLastPos = -1;
-			_pickedUpPieceRot = 0;
-		}
+	order.resize(24);
+	rotations.resize(24);
+
+	// A piece may still be held while saving; make sure the saved data
+	// has it back in the last place it was picked up from
+	if (_pickedUpPieceID != -1) {
+		order[_pickedUpPieceLastPos] = _pickedUpPieceID;
+		rotations[_pickedUpPieceLastPos] = _pickedUpPieceRot;
+		_pickedUpPieceID = -1;
+		_pickedUpPieceLastPos = -1;
+		_pickedUpPieceRot = 0;
 	}
 
-	ser.syncArray(order.data(), 24, Common::Serializer::Byte);
+	ser.syncArray(order.data(), order.size(), Common::Serializer::Byte);
 	ser.syncArray(rotations.data(), 24, Common::Serializer::Byte);
 }
 


Commit: 3b555f1c6ce5e3fd2d3093d73f74a9d1504531eb
    https://github.com/scummvm/scummvm/commit/3b555f1c6ce5e3fd2d3093d73f74a9d1504531eb
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2025-11-11T19:58:23+01:00

Commit Message:
NANCY: Fix overwrite dialog in nancy8 save menu

The "do you want to overwrite this save?" message was
erroneously left out of the new save/load menu.

Changed paths:
    engines/nancy/state/loadsave.cpp
    engines/nancy/state/loadsave.h


diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index cd68299e3b9..be3c92ea433 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -201,6 +201,45 @@ void LoadSaveMenu::enterFilename() {
 	}
 }
 
+bool LoadSaveMenu::save() {
+	auto *sdlg = GetEngineData(SDLG);
+
+	if (sdlg && sdlg->dialogs.size() > 1) {
+		// nancy6 added a "Do you want to overwrite this save" dialog.
+		// First, check if we are actually overwriting
+		SaveStateDescriptor desc = g_nancy->getMetaEngine()->querySaveMetaInfos(ConfMan.getActiveDomainName().c_str(), _selectedSave + 1);
+		if (desc.isValid()) {
+			if (!ConfMan.hasKey("sdlg_return", Common::ConfigManager::kTransientDomain)) {
+				// Request the dialog
+				ConfMan.setInt("sdlg_id", 1, Common::ConfigManager::kTransientDomain);
+				_destroyOnExit = false;
+				g_nancy->setState(NancyState::kSaveDialog);
+				return false;
+			} else {
+				// Dialog has returned
+				g_nancy->_graphics->suppressNextDraw();
+				_destroyOnExit = true;
+				uint ret = ConfMan.getInt("sdlg_return", Common::ConfigManager::kTransientDomain);
+				ConfMan.removeKey("sdlg_return", Common::ConfigManager::kTransientDomain);
+				switch (ret) {
+				case 1 :
+					// "No" keeps us in the LoadSave state but doesn't save
+					_state = kRun;
+					return false;
+				case 2 :
+					// "Cancel" returns to the main menu
+					g_nancy->setState(NancyState::kMainMenu);
+					return false;
+				default:
+					// "Yes" actually saves
+					break;
+				}
+			}
+		}
+	}
+	return true;
+}
+
 void LoadSaveMenu::load() {
 	auto *sdlg = GetEngineData(SDLG);
 
@@ -626,41 +665,9 @@ void LoadSaveMenu_V1::enterFilename() {
 	}
 }
 
-void LoadSaveMenu_V1::save() {
-	auto *sdlg = GetEngineData(SDLG);
-
-	if (sdlg && sdlg->dialogs.size() > 1) {
-		// nancy6 added a "Do you want to overwrite this save" dialog.
-		// First, check if we are actually overwriting
-		SaveStateDescriptor desc = g_nancy->getMetaEngine()->querySaveMetaInfos(ConfMan.getActiveDomainName().c_str(), _selectedSave + 1);
-		if (desc.isValid()) {
-			if (!ConfMan.hasKey("sdlg_return", Common::ConfigManager::kTransientDomain)) {
-				// Request the dialog
-				ConfMan.setInt("sdlg_id", 1, Common::ConfigManager::kTransientDomain);
-				_destroyOnExit = false;
-				g_nancy->setState(NancyState::kSaveDialog);
-				return;
-			} else {
-				// Dialog has returned
-				g_nancy->_graphics->suppressNextDraw();
-				_destroyOnExit = true;
-				uint ret = ConfMan.getInt("sdlg_return", Common::ConfigManager::kTransientDomain);
-				ConfMan.removeKey("sdlg_return", Common::ConfigManager::kTransientDomain);
-				switch (ret) {
-				case 1 :
-					// "No" keeps us in the LoadSave state but doesn't save
-					_state = kRun;
-					return;
-				case 2 :
-					// "Cancel" returns to the main menu
-					g_nancy->setState(NancyState::kMainMenu);
-					return;
-				default:
-					// "Yes" actually saves
-					break;
-				}
-			}
-		}
+bool LoadSaveMenu_V1::save() {
+	if (!LoadSaveMenu::save()) {
+		return false;
 	}
 
 	// Improvement: not providing a name doesn't result in the
@@ -719,6 +726,7 @@ void LoadSaveMenu_V1::save() {
 
 	_saveExists[_selectedSave] = true;
 	g_nancy->_hasJustSaved = true;
+	return true;
 }
 
 int LoadSaveMenu_V1::scummVMSaveSlotToLoad() const {
@@ -1166,7 +1174,11 @@ void LoadSaveMenu_V2::enterFilename() {
 	}
 }
 
-void LoadSaveMenu_V2::save() {
+bool LoadSaveMenu_V2::save() {
+	if (!LoadSaveMenu::save()) {
+		return false;
+	}
+
 	Common::String finalDesc = _enteredString;
 
 	// Look for a state with a matching name and overwrite it
@@ -1213,6 +1225,7 @@ void LoadSaveMenu_V2::save() {
 
 	_saveExists[_selectedSave] = true;
 	g_nancy->_hasJustSaved = true;
+	return true;
 }
 
 void LoadSaveMenu_V2::success() {
diff --git a/engines/nancy/state/loadsave.h b/engines/nancy/state/loadsave.h
index 8eaf602c9ff..b6601dbc07d 100644
--- a/engines/nancy/state/loadsave.h
+++ b/engines/nancy/state/loadsave.h
@@ -50,7 +50,7 @@ protected:
 	virtual void init() = 0;
 	virtual void run() = 0;
 	virtual void enterFilename();
-	virtual void save() = 0;
+	virtual bool save();
 	virtual void load();
 	virtual void success();
 	virtual void stop();
@@ -97,7 +97,7 @@ private:
 	void init() override;
 	void run() override;
 	void enterFilename() override;
-	void save() override;
+	bool save() override;
 
 	virtual int scummVMSaveSlotToLoad() const override;
 
@@ -118,7 +118,7 @@ private:
 	void init() override;
 	void run() override;
 	void enterFilename() override;
-	void save() override;
+	bool save() override;
 	void success() override;
 
 	virtual int scummVMSaveSlotToLoad() const override;


Commit: 0ad9953c49dab229ea86d290d808de97945414cf
    https://github.com/scummvm/scummvm/commit/0ad9953c49dab229ea86d290d808de97945414cf
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2025-11-11T19:58:23+01:00

Commit Message:
NANCY: Fix calling of phone numbers not in list

This fixes two bugs that were causing "loose" phone
numbers in nancy8 (not in directory) to not get called.

The first one is that our code was erroneously assuming
the event flag condition in the Call struct was for
whether the call should be connected at all; in fact,
it's only used to filter out numbers from the directory
listing, but they should still be valid.

The second one is that the dial button would always
overwrite the user-provided phone number with
the first call entry, which would then fail its flag check.
This has now been fixed, and user input is actually
evaluated.

Changed paths:
    engines/nancy/action/puzzle/telephone.cpp
    engines/nancy/action/puzzle/telephone.h


diff --git a/engines/nancy/action/puzzle/telephone.cpp b/engines/nancy/action/puzzle/telephone.cpp
index ca121e00e1c..05d75514592 100644
--- a/engines/nancy/action/puzzle/telephone.cpp
+++ b/engines/nancy/action/puzzle/telephone.cpp
@@ -135,7 +135,7 @@ void Telephone::readData(Common::SeekableReadStream &stream) {
 		PhoneCall &call = _calls[i];
 
 		if (_isNewPhone) {
-			call.eventFlagCondition = stream.readSint16LE();
+			call.directoryDisplayCondition = stream.readSint16LE();
 		}
 
 		call.phoneNumber.resize(11);
@@ -194,17 +194,11 @@ void Telephone::execute() {
 				// We do this before going to the ringing state to support nancy4's voice mail system,
 				// where call numbers can be 1 digit long
 				for (uint i = 0; i < _calls.size(); ++i) {
-					// Do not evaluate phone calls whose condition isn't met
-					if (_calls[i].eventFlagCondition != kEvNoEvent) {
-						if (NancySceneState.getEventFlag(_calls[i].eventFlagCondition, g_nancy->_false)) {
-							continue;
-						}
-					}
-
+					auto &call = _calls[i];
 					bool invalid = false;
 
 					for (uint j = 0; j < _calledNumber.size(); ++j) {
-						if (_calledNumber[j] != _calls[i].phoneNumber[j]) {
+						if (_calledNumber[j] != call.phoneNumber[j]) {
 							// Invalid number, move onto next
 							invalid = true;
 							break;
@@ -456,9 +450,11 @@ void Telephone::handleInput(NancyInput &input) {
 			bool changeDirectoryEntry = false;
 			int dirEntryDelta = 1;
 			if (_dialButtonID != -1 && buttonNr == _dialButtonID) {
-				_calledNumber = _calls[_displayedDirectory].phoneNumber;
-				while (_calledNumber.back() == 10) {
-					_calledNumber.pop_back();
+				if (_isShowingDirectory) {
+					_calledNumber = _calls[_displayedDirectory].phoneNumber;
+					while (_calledNumber.back() == 10) {
+						_calledNumber.pop_back();
+					}
 				}
 
 				_checkNumbers = true;
@@ -550,11 +546,11 @@ void Telephone::handleInput(NancyInput &input) {
 						_displayedDirectory = _calls.size() - 1;
 					}
 
-					if (_calls[_displayedDirectory].eventFlagCondition == kEvNoEvent) {
+					if (_calls[_displayedDirectory].directoryDisplayCondition == kEvNoEvent) {
 						break;
 					}
 
-					if (NancySceneState.getEventFlag(_calls[_displayedDirectory].eventFlagCondition, g_nancy->_true)) {
+					if (NancySceneState.getEventFlag(_calls[_displayedDirectory].directoryDisplayCondition, g_nancy->_true)) {
 						break;
 					}
 
diff --git a/engines/nancy/action/puzzle/telephone.h b/engines/nancy/action/puzzle/telephone.h
index 0596727496f..c2b34bcbd0b 100644
--- a/engines/nancy/action/puzzle/telephone.h
+++ b/engines/nancy/action/puzzle/telephone.h
@@ -39,7 +39,7 @@ public:
 		SceneChangeWithFlag sceneChange;
 
 		// NewPhone members
-		int16 eventFlagCondition = -1;
+		int16 directoryDisplayCondition = -1;
 		Common::Rect displaySrc;
 	};
 




More information about the Scummvm-git-logs mailing list