87e82cc574dd62829bf1bfe9b7db30396576840f

Author
outfoxxed <outfoxxed@outfoxxed.me>
Committer
outfoxxed <outfoxxed@outfoxxed.me>
Date

Message

Fix UAF in root node

The root node's last focused child could be freed without the root
node being updated. This broke the selection hook which uses `root->getFocusedNode()`.

Diff

 1diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp
 2index 5889d18fa6426bc8efbf6ec26c53507068db9276..3fbb063863c2902c68a8163a73c15010d766cfd6 100644
 3--- a/src/Hy3Layout.cpp
 4+++ b/src/Hy3Layout.cpp
 5@@ -295,12 +295,23 @@ Hy3Node* Hy3Node::removeFromParentRecursive() {
 6 
 7 	Debug::log(LOG, "Recursively removing parent nodes of %p", parent);
 8 
 9-	while (parent->parent != nullptr) {
10+	while (parent != nullptr) {
11+		if (parent->parent == nullptr) {
12+			Debug::log(ERR, "* UAF DEBUGGING - %p's parent is null, its the root group", parent);
13+
14+			if (parent == this) {
15+				Debug::log(ERR, "* UAF DEBUGGING - returning nullptr as this == root group");
16+			} else {
17+				Debug::log(ERR, "* UAF DEBUGGING - deallocing %p and returning nullptr", parent);
18+				parent->layout->nodes.remove(*parent);
19+			}
20+			return nullptr;
21+		}
22+
23 		auto* child = parent;
24 		parent = parent->parent;
25 		auto& group = parent->data.as_group;
26 
27-
28 		if (group.children.size() > 2) {
29 			auto iter = std::find(group.children.begin(), group.children.end(), child);
30 
31@@ -323,10 +334,12 @@ Hy3Node* Hy3Node::removeFromParentRecursive() {
32 
33 		if (child != this) {
34 			parent->layout->nodes.remove(*child);
35+		} else {
36+			child->parent = nullptr;
37 		}
38 
39 		if (!group.children.empty()) {
40-			auto splitmod = group.children.empty() ? 0.0 : -((1.0 - child->size_ratio) / group.children.size());
41+			auto splitmod = -((1.0 - child->size_ratio) / group.children.size());
42 
43 			for (auto* child: group.children) {
44 				child->size_ratio += splitmod;
45@@ -1248,7 +1261,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus(Hy3Node& node, ShiftDirection direction, boo
46 		node.parent = target_group;
47 		node.size_ratio = 1.0;
48 
49-		old_parent->recalcSizePosRecursive();
50+		if (old_parent != nullptr) old_parent->recalcSizePosRecursive();
51 		target_group->recalcSizePosRecursive();
52 
53 		auto* target_parent = target_group->parent;