Bug 636697 - Crash calling null setter in js_watch_set. r=brendan.

This commit is contained in:
Jason Orendorff 2011-03-03 14:24:13 -06:00
parent 8366fbaf5b
commit 29ac094796
3 changed files with 30 additions and 6 deletions

View File

@ -718,19 +718,30 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
wp = (JSWatchPoint *)wp->links.next) {
const Shape *shape = wp->shape;
if (wp->object == obj && SHAPE_USERID(shape) == id && !(wp->flags & JSWP_HELD)) {
bool ok;
Value old;
uint32 slot;
const Shape *needMethodSlotWrite = NULL;
wp->flags |= JSWP_HELD;
DBG_UNLOCK(rt);
jsid propid = shape->id;
shape = obj->nativeLookup(propid);
if (!shape) {
/*
* This happens if the watched property has been deleted, but a
* prototype has a watched accessor property with the same
* name. See bug 636697.
*/
ok = true;
goto out;
}
JS_ASSERT(IsWatchedProperty(cx, shape));
jsid userid = SHAPE_USERID(shape);
/* Determine the property's old value. */
bool ok;
uint32 slot = shape->slot;
Value old = obj->containsSlot(slot) ? obj->nativeGetSlot(slot) : UndefinedValue();
const Shape *needMethodSlotWrite = NULL;
slot = shape->slot;
old = obj->containsSlot(slot) ? obj->nativeGetSlot(slot) : UndefinedValue();
if (shape->isMethod()) {
/*
* We get here in two cases: (1) the existing watched property
@ -793,7 +804,8 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
? ExternalInvoke(cx, ObjectValue(*obj),
ObjectValue(*CastAsObject(wp->setter)),
1, vp, vp)
: CallJSPropertyOpSetter(cx, wp->setter, obj, userid, strict, vp);
: CallJSPropertyOpSetter(cx, wp->setter, obj, SHAPE_USERID(shape),
strict, vp);
} else if (shape == needMethodSlotWrite) {
/* See comment above about needMethodSlotWrite. */
obj->nativeSetSlot(shape->slot, *vp);

View File

@ -34,3 +34,4 @@ script regress-627984-6.js
script regress-627984-7.js
script regress-630377.js
script regress-631723.js
script regress-636697.js

View File

@ -0,0 +1,11 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var a = {set p(x) {}};
a.watch('p', function () {});
var b = Object.create(a);
b.watch('p', function () {});
delete b.p;
b.p = 0;
reportCompare(0, 0, 'ok');