ref: a9e6b4cd017e594964a56c2294875c4240b1ead8
parent: 051d504cfbe8f6034ba18df72858b62b1d8570b4
author: Tor Andersson <tor.andersson@artifex.com>
date: Sat Nov 1 09:01:05 EDT 2014
Fix bug in maintaining property enumeration list. The tail pointer in the linked list head was mismanaged, leading to using free memory when properties are inserted after deleting a property such that the tail points to the deleted node.
--- a/jsproperty.c
+++ b/jsproperty.c
@@ -97,15 +97,17 @@
return *result = newproperty(J, name);
}
-static void freeproperty(js_State *J, js_Property *node)
+static void freeproperty(js_State *J, js_Object *obj, js_Property *node)
{
if (node->next)
node->next->prevp = node->prevp;
+ else
+ obj->tailp = node->prevp;
*node->prevp = node->next;
js_free(J, node);
}
-static js_Property *delete(js_State *J, js_Property *node, const char *name)
+static js_Property *delete(js_State *J, js_Object *obj, js_Property *node, const char *name)
{
js_Property *temp, *succ;
@@ -112,18 +114,18 @@
if (node != &sentinel) {
int c = strcmp(name, node->name);
if (c < 0) {
- node->left = delete(J, node->left, name);
+ node->left = delete(J, obj, node->left, name);
} else if (c > 0) {
- node->right = delete(J, node->right, name);
+ node->right = delete(J, obj, node->right, name);
} else {
if (node->left == &sentinel) {
temp = node;
node = node->right;
- freeproperty(J, temp);
+ freeproperty(J, obj, temp);
} else if (node->right == &sentinel) {
temp = node;
node = node->left;
- freeproperty(J, temp);
+ freeproperty(J, obj, temp);
} else {
succ = node->right;
while (succ->left != &sentinel)
@@ -131,7 +133,7 @@
node->name = succ->name;
node->atts = succ->atts;
node->value = succ->value;
- node->right = delete(J, node->right, succ->name);
+ node->right = delete(J, obj, node->right, succ->name);
}
}
@@ -162,6 +164,8 @@
obj->type = type;
obj->properties = &sentinel;
+ obj->head = NULL;
+ obj->tailp = &obj->head;
obj->prototype = prototype;
obj->extensible = 1;
return obj;
@@ -205,14 +209,9 @@
obj->properties = insert(J, obj->properties, name, &result);
if (!result->prevp) {
- if (!obj->head) {
- result->prevp = &obj->head;
- obj->tail = obj->head = result;
- } else {
- result->prevp = &obj->tail->next;
- obj->tail->next = result;
- obj->tail = result;
- }
+ result->prevp = obj->tailp;
+ *obj->tailp = result;
+ obj->tailp = &result->next;
}
return result;
}
@@ -219,7 +218,7 @@
void jsV_delproperty(js_State *J, js_Object *obj, const char *name)
{
- obj->properties = delete(J, obj->properties, name);
+ obj->properties = delete(J, obj, obj->properties, name);
}
/* Flatten hierarchy of enumerable properties into an iterator object */
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -62,7 +62,7 @@
enum js_Class type;
int extensible;
js_Property *properties;
- js_Property *head, *tail; /* for enumeration */
+ js_Property *head, **tailp; /* for enumeration */
js_Object *prototype;
union {
int boolean;
@@ -101,7 +101,7 @@
{
const char *name;
js_Property *left, *right;
- js_Property **prevp, *next; /* for enumeration */
+ js_Property *next, **prevp; /* for enumeration */
int level;
int atts;
js_Value value;