aboutsummaryrefslogtreecommitdiff
path: root/include/cru/ui/render/LayoutRenderObject.h
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-11-20 03:00:16 +0800
committerYuqian Yang <crupest@crupest.life>2025-11-20 03:00:16 +0800
commit478b4cdce5c584c294d38f84a0131f239d9af88f (patch)
tree74ad9ae123869195c4ce845f9ce34c4425a62b3d /include/cru/ui/render/LayoutRenderObject.h
parent2eb34dfc3dd3ca718da6ebf049886b4ae140b332 (diff)
downloadcru-478b4cdce5c584c294d38f84a0131f239d9af88f.tar.gz
cru-478b4cdce5c584c294d38f84a0131f239d9af88f.tar.bz2
cru-478b4cdce5c584c294d38f84a0131f239d9af88f.zip
Fix use after free in render object.
Diffstat (limited to 'include/cru/ui/render/LayoutRenderObject.h')
-rw-r--r--include/cru/ui/render/LayoutRenderObject.h21
1 files changed, 18 insertions, 3 deletions
diff --git a/include/cru/ui/render/LayoutRenderObject.h b/include/cru/ui/render/LayoutRenderObject.h
index 11df0449..c0e4218d 100644
--- a/include/cru/ui/render/LayoutRenderObject.h
+++ b/include/cru/ui/render/LayoutRenderObject.h
@@ -13,6 +13,8 @@ class LayoutRenderObject : public RenderObject {
struct ChildData {
RenderObject* render_object;
ChildLayoutData layout_data;
+ bool render_object_destroyed;
+ EventHandlerRevokerListGuard event_guard;
};
protected:
@@ -33,21 +35,34 @@ class LayoutRenderObject : public RenderObject {
if (position < 0) position = 0;
if (position > GetChildCount()) position = GetChildCount();
children_.insert(children_.begin() + position,
- ChildData{render_object, ChildLayoutData()});
+ ChildData{render_object, ChildLayoutData(), false});
render_object->SetParent(this);
+ render_object->DestroyEvent()->AddSpyOnlyHandler([this, render_object] {
+ auto iter = std::ranges::find_if(
+ children_, [render_object](const ChildData& data) {
+ return data.render_object == render_object;
+ });
+ if (iter != children_.cend()) {
+ iter->render_object_destroyed = true;
+ }
+ });
InvalidateLayout();
}
void RemoveChild(Index position) {
Expects(position >= 0 && position < GetChildCount());
- children_[position].render_object->SetParent(nullptr);
+ if (!children_[position].render_object_destroyed) {
+ children_[position].render_object->SetParent(nullptr);
+ }
children_.erase(children_.begin() + position);
InvalidateLayout();
}
void ClearChildren() {
for (auto child : children_) {
- child.render_object->SetParent(nullptr);
+ if (!child.render_object_destroyed) {
+ child.render_object->SetParent(nullptr);
+ }
}
children_.clear();
InvalidateLayout();