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 ownership validation for the source object in four MSG_DO_SPECIAL_POWER variants, guarded by #if !RETAIL_COMPATIBLE_CRC. All four blocks share a latent null-pointer dereference: getControllingPlayer() is called a second time inside the DEBUG_CRASH format string without a null guard, which crashes in debug builds if the source object has no controlling player. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Receive MSG_DO_SPECIAL_POWER variant] --> B{source != nullptr?}
B -- No --> E[Use currentlySelectedGroup]
B -- Yes --> C{RETAIL_COMPATIBLE_CRC?}
C -- Yes, retail build --> F[Execute special power command]
C -- No, dev/debug build --> D{getControllingPlayer == thisPlayer?}
D -- Yes, owner matches --> F
D -- No, wrong owner --> G[Enter DEBUG_CRASH block]
G --> H{getControllingPlayer returns null?}
H -- Not null --> I[Log error message and break]
H -- Is null --> J[NULL DEREFERENCE CRASH]
F --> K[groupDoSpecialPower / variant]
Last reviewed commit: 45ef03d
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
Outdated
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.
There was a problem hiding this comment.
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 is also my concern. If it was crashing, then its fine to omit RETAIL_COMPATIBLE_CRC, but if the game kept on working, then cheated behavior may be more acceptable than mismatch. Not sure. Mismatch is game ending. Cheat is not.
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