eval第二引数permission denied
こっちはわりと素直。
jsobj.c
/* * Script.prototype.compile/exec and Object.prototype.eval all take an * optional trailing argument that overrides the scope object. */ if (argc >= 2) { if (!js_ValueToObject(cx, argv[1], &scopeobj)) return JS_FALSE; argv[1] = OBJECT_TO_JSVAL(scopeobj); } ..... /* Ensure we compile this eval with the right object in the scope chain. */ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str);
evalの第二引数のスコープチェインをたどる。
JSObject * js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller) { JSClass *clasp; JSExtendedClass *xclasp; JSObject *inner; if (!scopeobj) goto bad; OBJ_TO_INNER_OBJECT(cx, scopeobj); if (!scopeobj) return NULL; inner = scopeobj; /* XXX This is an awful gross hack. */ while (scopeobj) { clasp = OBJ_GET_CLASS(cx, scopeobj); if (clasp->flags & JSCLASS_IS_EXTENDED) { xclasp = (JSExtendedClass*)clasp; if (xclasp->innerObject && xclasp->innerObject(cx, scopeobj) != scopeobj) { goto bad; } } scopeobj = OBJ_GET_PARENT(cx, scopeobj); } return inner; bad: JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_INDIRECT_CALL, caller); return NULL; }
その途中にJSCLASS_IS_EXTENDEDのクラスがあったらNG.
spidermonkey内部にはJSClassというのとJSExtendedClassというのがあってJSCLASS_IS_EXTENDEDというのは後者のときにセットされているフラグ。
XPCOMコンポーネントなどのXPCWrapperdNativeを通してアクセスされるオブジェクトは、spidermonkeyの中で内部的に生成されるクラスがJSExtendedClassになっている。
第二引数に渡すオブジェクトが、ユーザがスクリプト内で定義したjavascriptのクラスであればJSExtendedClassではなくJSClassなのでチェックをパスできる。が、スクリプトで定義されたものではなくXPCOM由来オブジェクトなどを第二引数に渡すと、ここのチェックにひっかかって JSMSG_BAD_INDIRECT_CALL が出る。(function eval must be called directly, and not by way of a function of another nameってやつ)