shithub: libmujs

Download patch

ref: 09b3fcb1e7ec420926affc4b6959cd5d8740c02a
parent: f882c6c5fea88ca1eca664b6755ba1d2a7c2b3f5
author: Tor Andersson <[email protected]>
date: Mon Nov 14 12:43:20 EST 2022

Bug 706075: Fix errors in property deletion.

1) Copy "level" from the replacement node.
2) Fix rebalancing by using exact algorithm from AA-tree paper.

--- a/jsproperty.c
+++ b/jsproperty.c
@@ -104,36 +104,43 @@
 	--obj->count;
 }
 
-static js_Property *unlinkproperty(js_State *J, js_Object *obj, js_Property *node, const char *name, js_Property **garbage)
+static js_Property *unlinkproperty(js_Property *node, const char *name, js_Property **garbage)
 {
-	js_Property *temp, *succ;
-
+	js_Property *temp, *a, *b;
 	if (node != &sentinel) {
 		int c = strcmp(name, node->name);
 		if (c < 0) {
-			node->left = unlinkproperty(J, obj, node->left, name, garbage);
+			node->left = unlinkproperty(node->left, name, garbage);
 		} else if (c > 0) {
-			node->right = unlinkproperty(J, obj, node->right, name, garbage);
+			node->right = unlinkproperty(node->right, name, garbage);
 		} else {
-			if (node->left == &sentinel) {
-				*garbage = node;
-				node = node->right;
-			} else if (node->right == &sentinel) {
-				*garbage = node;
-				node = node->left;
-			} else {
-				*garbage = node;
-				succ = node->right;
-				while (succ->left != &sentinel)
-					succ = succ->left;
-				succ->right = unlinkproperty(J, obj, node->right, succ->name, &temp);
-				succ->left = node->left;
-				node = succ;
+			*garbage = node;
+			if (node->left == &sentinel && node->right == &sentinel) {
+				return &sentinel;
 			}
+			else if (node->left == &sentinel) {
+				a = node->right;
+				while (a->left != &sentinel)
+					a = a->left;
+				b = unlinkproperty(node->right, a->name, &temp);
+				temp->level = node->level;
+				temp->left = node->left;
+				temp->right = b;
+				node = temp;
+			}
+			else {
+				a = node->left;
+				while (a->right != &sentinel)
+					a = a->right;
+				b = unlinkproperty(node->left, a->name, &temp);
+				temp->level = node->level;
+				temp->left = b;
+				temp->right = node->right;
+				node = temp;
+			}
 		}
 
-		if (node->left->level < node->level - 1 ||
-			node->right->level < node->level - 1)
+		if (node->left->level < node->level - 1 || node->right->level < node->level - 1)
 		{
 			if (node->right->level > --node->level)
 				node->right->level = node->level;
@@ -149,9 +156,9 @@
 
 static js_Property *deleteproperty(js_State *J, js_Object *obj, js_Property *tree, const char *name)
 {
-	js_Property *garbage = NULL;
-	tree = unlinkproperty(J, obj, tree, name, &garbage);
-	if (garbage != NULL)
+	js_Property *garbage = &sentinel;
+	tree = unlinkproperty(tree, name, &garbage);
+	if (garbage != &sentinel)
 		freeproperty(J, obj, garbage);
 	return tree;
 }