ref: edb50ad66f7601ca9a3544a0e9045e8a8c60561f
parent: bf4ac9420739b4ac3bc963bd2c7b69de36a8bb11
author: Tor Andersson <tor.andersson@artifex.com>
date: Mon Nov 7 07:52:05 EST 2022
Bug 706057: Fix use-after-free in getOwnPropertyDescriptor. getOwnPropertyDescriptor should create the descriptor object by using [[DefineOwnProperty]], and not by looking through the prototype chain where it may invoke getters and setters on the Object.prototype. If there exists an Object.prototype.get property with a setter, that method is invoked when it shouldn't. A malicious getter here can delete the property currently being processed in getOwnPropertyDescriptor, and we'll end up with a use-after-free bug. Avoid this problem by following the spec and use js_defproperty rather than js_setproperty to define own properties in getOwnPropertyDescriptor and related functions.
--- a/jsobject.c
+++ b/jsobject.c
@@ -134,25 +134,25 @@
js_newobject(J);
if (!ref->getter && !ref->setter) {
js_pushvalue(J, ref->value);
- js_setproperty(J, -2, "value");
+ js_defproperty(J, -2, "value", 0);
js_pushboolean(J, !(ref->atts & JS_READONLY));
- js_setproperty(J, -2, "writable");
+ js_defproperty(J, -2, "writable", 0);
} else {
if (ref->getter)
js_pushobject(J, ref->getter);
else
js_pushundefined(J);
- js_setproperty(J, -2, "get");
+ js_defproperty(J, -2, "get", 0);
if (ref->setter)
js_pushobject(J, ref->setter);
else
js_pushundefined(J);
- js_setproperty(J, -2, "set");
+ js_defproperty(J, -2, "set", 0);
}
js_pushboolean(J, !(ref->atts & JS_DONTENUM));
- js_setproperty(J, -2, "enumerable");
+ js_defproperty(J, -2, "enumerable", 0);
js_pushboolean(J, !(ref->atts & JS_DONTCONF));
- js_setproperty(J, -2, "configurable");
+ js_defproperty(J, -2, "configurable", 0);
}
}
@@ -248,7 +248,7 @@
}
if (js_hasproperty(J, -1, "value")) {
hasvalue = 1;
- js_setproperty(J, -3, name);
+ js_defproperty(J, -3, name, 0);
}
if (!writable) atts |= JS_READONLY;