Skip to content

Commit dd9446b

Browse files
committed
fix removeAllChildren UB
1 parent efdde0a commit dd9446b

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <Geode/Geode.hpp>
2+
#include <Geode/utils/VMTHookManager.hpp>
3+
#include <Geode/modify/Traits.hpp>
4+
#include <Geode/modify/CCMenu.hpp>
5+
6+
using namespace geode::prelude;
7+
8+
struct CCMenuSelectedFix : Modify<CCMenuSelectedFix, CCMenu> {
9+
bool initWithArray(CCArray* arr) {
10+
if (!CCMenu::initWithArray(arr)) return false;
11+
12+
if (!exact_cast<CCMenu*>(this)) {
13+
return true;
14+
}
15+
16+
auto hook = VMTHookManager::get().addHook<
17+
geode::modifier::ResolveC<CCMenuSelectedFix>::func(&CCMenuSelectedFix::removeAllChildren)
18+
>(this, "cocos2d::CCMenu::removeAllChildren");
19+
20+
if (!hook) {
21+
log::error("Failed to hook CCMenu::removeAllChildren: {}", hook.unwrapErr());
22+
}
23+
24+
return true;
25+
}
26+
27+
$override
28+
void removeAllChildren() {
29+
// CCMenu itself overrides `removeChild` to reset `m_pSelectedItem` and prevent UB.
30+
// `removeAllChildren` is not overriden and never calls `removeChild`, thus not resetting this member.
31+
// This fixes that, eliminating UB that can happen when spam clicking a button that removes itself with this method.
32+
m_pSelectedItem = nullptr;
33+
CCNode::removeAllChildren();
34+
}
35+
};

0 commit comments

Comments
 (0)