Hey,

I'm trying to work out the vulnerability in Firefox 10.0.2 related to array_join (CVE-2012-0464: http://cve.mitre.org/cgi-bin/cvename...=CVE-2012-0464).
As I understood from the Advisory, the array_join function is vulnerable to a dangling pointer attack.

To fix this vulnerability Mozilla replaced the js_ValueToString function to a similar ToString function.
Code:
ToString(JSContext *cx, const js::Value &v)
{
    if (v.isString())
         return v.toString();
     return ToStringSlow(cx, v);
}
Unlike the js_ValueToString, this function checks if the value provided is a String. The ToStringSlow function is the exact match to the js_valueTOString function. So I'm guessing the vulnerability relates to a string object.

Therefore my assumptions,
1. [1,2,3].join(new String) would call the function array_join with the new String object rooted to args[0];
2. ...
3. The object needs to be unrooted and thereby facing garbage collection.

ToPrimitive calls the toString method of the string to get its string value. We can control the callback by changing String.prototype.toString to point to our custom function. I believe this is where I clean the object.

Any advices?


Code:
//In [10.0.2]
array_join(JSContext *cx, uintN argc, Value *vp)
{
    JS_CHECK_RECURSION(cx, return false);

    CallArgs args = CallArgsFromVp(argc, vp);
    JSString *str;
    if (args.length() == 0 || args[0].isUndefined()) {
        str = NULL;
    } else {
        str = js_ValueToString(cx, args[0]);       (1)
        if (!str)
            return JS_FALSE;
        args[0].setString(str);
    }
    JSObject *obj = ToObject(cx, &args.thisv());
    if (!obj)
        return false;
    return array_toString_sub(cx, obj, JS_FALSE, str, args);
}
Code:
js_ValueToString(JSContext *cx, const Value &arg)
{
    Value v = arg;
    if (!ToPrimitive(cx, JSTYPE_STRING, &v))
        return NULL;

    JSString *str;
    if (v.isString()) {
        str = v.toString();
    } else if (v.isInt32()) {
        str = js_IntToString(cx, v.toInt32());
    } else if (v.isDouble()) {
        str = js_NumberToString(cx, v.toDouble());
    } else if (v.isBoolean()) {
        str = js_BooleanToString(cx, v.toBoolean());
    } else if (v.isNull()) {
        str = cx->runtime->atomState.nullAtom;
    } else {
        str = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
    }
    return str;
}
Code:
//In [11.0]
array_join(JSContext *cx, uintN argc, Value *vp)
{
   ...
    str = ToString(cx, args[0]);  //Everything else same as the array_join in [10.0.2] 
                                  //js_ValueToString replaced by ToString. 
   ...
}