Skip to content

bugfix(money): Fix undefined behavior for starting cash combo box#2582

Open
Caball009 wants to merge 2 commits intoTheSuperHackers:mainfrom
Caball009:fix_oob_custom_starting_money
Open

bugfix(money): Fix undefined behavior for starting cash combo box#2582
Caball009 wants to merge 2 commits intoTheSuperHackers:mainfrom
Caball009:fix_oob_custom_starting_money

Conversation

@Caball009
Copy link
Copy Markdown

@Caball009 Caball009 commented Apr 11, 2026

Players that modify their GlobalData::m_defaultStartingCash value may see strange behavior when it comes to their starting cash (skirmish and multiplayer). That's because the game dereferences an end iterator if it cannot find one of the four default starting cash values. This crashes the game in debug builds and it may produce 'random' starting cash values in release builds. (Even though the starting cash is unsigned, the visual amount may show up as negative in the control bar).

TODO:

  • Replicate in Generals.

@Caball009 Caball009 added Major Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Stability Concerns stability of the runtime Crash This is a crash, very bad labels Apr 11, 2026
@Caball009 Caball009 changed the title bugfix(money): Fix undefined behavior for starting cash combo box. bugfix(money): Fix undefined behavior for starting cash combo box Apr 11, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 11, 2026

Greptile Summary

This PR fixes undefined behavior in PopulateStartingCashComboBox (Zero Hour / GeneralsMD) where the post-loop it iterator — pointing to end() — was dereferenced to retrieve item data for a custom starting-cash value not present in the standard list. The fix replaces it->countMoney() with myGame->getStartingCash().countMoney() in the fallback branch and scopes it inside the for loop to prevent the same mistake in future edits. It also removes a stale declaration of the same function from the vanilla Generals header, where no corresponding definition ever existed.

Confidence Score: 5/5

Safe to merge — the fix is minimal, targeted, and correct.

The only changed logic replaces an end-iterator dereference (definite UB) with the semantically correct value from myGame. The orphaned header declaration removal is pure cleanup with no behavioral impact. No new issues introduced.

No files require special attention.

Important Files Changed

Filename Overview
GeneralsMD/Code/GameEngine/Source/GameNetwork/GUIUtil.cpp Fixes UB caused by dereferencing the end iterator after the loop; also tightens it's scope to the loop itself.
Generals/Code/GameEngine/Include/GameNetwork/GUIUtil.h Removes orphaned declaration of PopulateStartingCashComboBox, which was never defined in the vanilla Generals code tree.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PopulateStartingCashComboBox called] --> B[Reset combo box]
    B --> C[Iterate over startingCashMap]
    C --> D{amountEqual current cash?}
    D -- Yes --> E[Set currentSelectionIndex = newIndex]
    D -- No --> C
    C -- Loop ends --> F{currentSelectionIndex == -1?}
    E --> F
    F -- No --> G[GadgetComboBoxSetSelectedPos]
    F -- Yes --> H[DEBUG_CRASH]
    H --> I[Add custom entry to combo box]
    I --> J["Set item data: myGame->getStartingCash().countMoney() ✅ (was: it->countMoney() on end iterator ❌)"]
    J --> G
Loading

Reviews (2): Last reviewed commit: "Removed unused function declaration in G..." | Re-trigger Greptile

@Caball009
Copy link
Copy Markdown
Author

Updated PR.

It looks like PopulateStartingCashComboBox doesn't exist in Generals, only the unused function declaration, which I removed.

void PopulateColorComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver = FALSE);
void PopulatePlayerTemplateComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool allowObservers );
void PopulateTeamComboBox(Int comboBox, GameWindow *comboArray[], GameInfo *myGame, Bool isObserver = FALSE);
void PopulateStartingCashComboBox(GameWindow *comboBox, GameInfo *myGame);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be here because we already merged code from Zero Hour to Generals. You can keep it.

@xezon xezon added this to the Stability fixes milestone Apr 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Crash This is a crash, very bad Gen Relates to Generals Major Severity: Minor < Major < Critical < Blocker Stability Concerns stability of the runtime ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants