fix(logic): Improve validation of MSG_DO_SPECIAL_POWER and variants in GameLogicDispatch#2380
Conversation
…n GameLogicDispatch
|
| Filename | Overview |
|---|---|
| GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp | Adds four identical ownership-validation blocks for MSG_DO_SPECIAL_POWER and variants; logic is sound and consistent with existing patterns in the file, but the DEBUG_CRASH message arguments dereference the result of getControllingPlayer() without a null guard, risking a secondary crash in debug builds if the source object has no controlling player. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["logicMessageDispatcher(msg)"] --> B["thisPlayer = getNthPlayer(msg->getPlayerIndex())"]
B --> C{MSG type?}
C --> D["MSG_DO_SPECIAL_POWER\nMSG_DO_SPECIAL_POWER_AT_LOCATION\nMSG_DO_SPECIAL_POWER_AT_OBJECT\nMSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION"]
D --> E["source = findObjectByID(sourceID)"]
E --> F{source != nullptr?}
F -- No --> G["Use currentlySelectedGroup"]
F -- Yes --> H{"source->getControllingPlayer()\n== thisPlayer?"}
H -- No --> I["DEBUG_CRASH diagnostic\n+ break (exit switch)"]
H -- Yes --> J["Create AIGroup\nadd(source)\ngroupDoSpecialPower(...)"]
J --> K["Destroy / removeAll AIGroup"]
Last reviewed commit: 1b37cba
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Show resolved
Hide resolved
|
Does this resolve an actual bug/crash or is it solving a potential issue in the future? |
xezon
left a comment
There was a problem hiding this comment.
Very important fix.
Can you do more audits over other messages for follow ups?
For example GameMessage::MSG_ENTER has no player check but GameMessage::MSG_EXIT does.
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Outdated
Show resolved
Hide resolved
Yes I should have some follow up PR's ready soon |
| if (source != nullptr) | ||
| { | ||
| // TheSuperHackers @fix stephanmeesters 01/03/2026 Validate the origin of the source object | ||
| if ( source->getControllingPlayer() != thisPlayer ) |
There was a problem hiding this comment.
One more thought on this: This would cause mismatch if someone cheated, for example with Control Hack. Are we ok with this?
It probably needs to go behind RETAIL_COMPATIBLE_CRC for the upmost correctness
There was a problem hiding this comment.
IMO mismatch is desirable here, and would be nice if the first release can have all these cases solid so it's a more "trustworthy" client (although, it doesn't actually communicate around that it did a good thing..)
There was a problem hiding this comment.
If we decide to go that route, then at least put a commented // #if RETAIL_COMPATIBLE_CRC and explain why we accept this mismatch.
There was a problem hiding this comment.
IMO mismatch is desirable here,
I agree. It's also consistent with all the other places that already check for the controlling player to prevent blatant abuse.
My only mild concern is that we may run into replays that mismatch because of this, and it's going to take time and effort to find out why they started to mismatch.
This PR improves the stability of network games by validating the origin of source objects in
MSG_DO_SPECIAL_POWERand related MSG variants inGameLogicDispatch. Tested on ~1k replays.Todo