mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 725576 - serialize principals only once per top-level script. r=luke
--HG-- extra : rebase_source : 92b82ff8a8d03d6176bf1e43329a59b77ca83de4
This commit is contained in:
parent
180e2b965e
commit
3b9873045c
@ -155,7 +155,7 @@ js::IsIdentifier(JSLinearString *str)
|
|||||||
/* Initialize members that aren't initialized in |init|. */
|
/* Initialize members that aren't initialized in |init|. */
|
||||||
TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *originPrin)
|
TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *originPrin)
|
||||||
: tokens(), cursor(), lookahead(), flags(), listenerTSData(), tokenbuf(cx),
|
: tokens(), cursor(), lookahead(), flags(), listenerTSData(), tokenbuf(cx),
|
||||||
cx(cx), originPrincipals(originPrin ? originPrin : prin)
|
cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin))
|
||||||
{
|
{
|
||||||
if (originPrincipals)
|
if (originPrincipals)
|
||||||
JSPRINCIPALS_HOLD(cx, originPrincipals);
|
JSPRINCIPALS_HOLD(cx, originPrincipals);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "jsdbgapi.h"
|
||||||
|
#include "jsxdrapi.h"
|
||||||
|
|
||||||
BEGIN_TEST(test_cloneScript)
|
BEGIN_TEST(test_cloneScript)
|
||||||
{
|
{
|
||||||
@ -48,3 +50,122 @@ BEGIN_TEST(test_cloneScript)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
END_TEST(test_cloneScript)
|
END_TEST(test_cloneScript)
|
||||||
|
|
||||||
|
void
|
||||||
|
DestroyPrincipals(JSContext *cx, JSPrincipals *principals)
|
||||||
|
{
|
||||||
|
delete principals;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Principals : public JSPrincipals
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Principals(const char *name)
|
||||||
|
{
|
||||||
|
refcount = 0;
|
||||||
|
codebase = const_cast<char *>(name);
|
||||||
|
destroy = DestroyPrincipals;
|
||||||
|
subsume = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AutoDropPrincipals
|
||||||
|
{
|
||||||
|
JSContext *cx;
|
||||||
|
JSPrincipals *principals;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoDropPrincipals(JSContext *cx, JSPrincipals *principals)
|
||||||
|
: cx(cx), principals(principals)
|
||||||
|
{
|
||||||
|
JSPRINCIPALS_HOLD(cx, principals);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AutoDropPrincipals()
|
||||||
|
{
|
||||||
|
JSPRINCIPALS_DROP(cx, principals);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
|
||||||
|
{
|
||||||
|
return JS_XDRBytes(xdr, reinterpret_cast<char *>(principalsp), sizeof(*principalsp));
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_TEST(test_cloneScriptWithPrincipals)
|
||||||
|
{
|
||||||
|
JSSecurityCallbacks cbs = {
|
||||||
|
NULL,
|
||||||
|
TranscodePrincipals,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_SetRuntimeSecurityCallbacks(rt, &cbs);
|
||||||
|
|
||||||
|
JSPrincipals *principalsA = new Principals("A");
|
||||||
|
AutoDropPrincipals dropA(cx, principalsA);
|
||||||
|
JSPrincipals *principalsB = new Principals("B");
|
||||||
|
AutoDropPrincipals dropB(cx, principalsB);
|
||||||
|
|
||||||
|
JSObject *A, *B;
|
||||||
|
|
||||||
|
CHECK(A = createGlobal(principalsA));
|
||||||
|
CHECK(B = createGlobal(principalsB));
|
||||||
|
|
||||||
|
const char *argnames[] = { "arg" };
|
||||||
|
const char *source = "return function() { return arg; }";
|
||||||
|
|
||||||
|
JSObject *obj;
|
||||||
|
|
||||||
|
// Compile in A
|
||||||
|
{
|
||||||
|
JSAutoEnterCompartment a;
|
||||||
|
if (!a.enter(cx, A))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSFunction *fun;
|
||||||
|
CHECK(fun = JS_CompileFunctionForPrincipals(cx, A, principalsA, "f",
|
||||||
|
mozilla::ArrayLength(argnames), argnames,
|
||||||
|
source, strlen(source), __FILE__, 1));
|
||||||
|
|
||||||
|
JSScript *script;
|
||||||
|
CHECK(script = JS_GetFunctionScript(cx, fun));
|
||||||
|
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == principalsA);
|
||||||
|
CHECK(obj = JS_GetFunctionObject(fun));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone into B
|
||||||
|
{
|
||||||
|
JSAutoEnterCompartment b;
|
||||||
|
if (!b.enter(cx, B))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSObject *cloned;
|
||||||
|
CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
|
||||||
|
|
||||||
|
JSFunction *fun;
|
||||||
|
CHECK(fun = JS_ValueToFunction(cx, JS::ObjectValue(*cloned)));
|
||||||
|
|
||||||
|
JSScript *script;
|
||||||
|
CHECK(script = JS_GetFunctionScript(cx, fun));
|
||||||
|
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == principalsB);
|
||||||
|
|
||||||
|
JS::Value v;
|
||||||
|
JS::Value args[] = { JS::Int32Value(1) };
|
||||||
|
CHECK(JS_CallFunctionValue(cx, B, JS::ObjectValue(*cloned), 1, args, &v));
|
||||||
|
CHECK(v.isObject());
|
||||||
|
|
||||||
|
JSObject *funobj = &v.toObject();
|
||||||
|
CHECK(JS_ObjectIsFunction(cx, funobj));
|
||||||
|
CHECK(fun = JS_ValueToFunction(cx, v));
|
||||||
|
CHECK(script = JS_GetFunctionScript(cx, fun));
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == principalsB);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
END_TEST(test_cloneScriptWithPrincipals)
|
||||||
|
@ -157,10 +157,40 @@ Error(JSContext *cx, const char (&input)[N])
|
|||||||
AutoInflatedString str(cx);
|
AutoInflatedString str(cx);
|
||||||
jsval dummy;
|
jsval dummy;
|
||||||
str = input;
|
str = input;
|
||||||
CHECK(!JS_ParseJSON(cx, str.chars(), str.length(), &dummy));
|
|
||||||
JS_ClearPendingException(cx);
|
ContextPrivate p = {0, 0};
|
||||||
|
CHECK(!JS_GetContextPrivate(cx));
|
||||||
|
JS_SetContextPrivate(cx, &p);
|
||||||
|
JSErrorReporter old = JS_SetErrorReporter(cx, reportJSONEror);
|
||||||
|
JSBool ok = JS_ParseJSON(cx, str.chars(), str.length(), &dummy);
|
||||||
|
JS_SetErrorReporter(cx, old);
|
||||||
|
JS_SetContextPrivate(cx, NULL);
|
||||||
|
|
||||||
|
CHECK(!ok);
|
||||||
|
CHECK(!p.unexpectedErrorCount);
|
||||||
|
CHECK(p.expectedErrorCount == 1);
|
||||||
|
|
||||||
|
/* We do not execute JS, so there should be no exception thrown. */
|
||||||
|
CHECK(!JS_IsExceptionPending(cx));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ContextPrivate {
|
||||||
|
unsigned unexpectedErrorCount;
|
||||||
|
unsigned expectedErrorCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
reportJSONEror(JSContext *cx, const char *message, JSErrorReport *report)
|
||||||
|
{
|
||||||
|
ContextPrivate *p = static_cast<ContextPrivate *>(JS_GetContextPrivate(cx));
|
||||||
|
if (report->errorNumber == JSMSG_JSON_BAD_PARSE)
|
||||||
|
p->expectedErrorCount++;
|
||||||
|
else
|
||||||
|
p->unexpectedErrorCount++;
|
||||||
|
}
|
||||||
|
|
||||||
END_TEST(testParseJSON_error)
|
END_TEST(testParseJSON_error)
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
|
@ -6,6 +6,236 @@
|
|||||||
#include "jsscript.h"
|
#include "jsscript.h"
|
||||||
#include "jsxdrapi.h"
|
#include "jsxdrapi.h"
|
||||||
|
|
||||||
|
static JSScript *
|
||||||
|
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals,
|
||||||
|
const char *bytes, size_t nbytes,
|
||||||
|
const char *filename, uintN lineno,
|
||||||
|
JSVersion version)
|
||||||
|
{
|
||||||
|
size_t nchars;
|
||||||
|
if (!JS_DecodeBytes(cx, bytes, nbytes, NULL, &nchars))
|
||||||
|
return NULL;
|
||||||
|
jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
|
||||||
|
if (!chars)
|
||||||
|
return NULL;
|
||||||
|
JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
|
||||||
|
JSScript *script = JS_CompileUCScriptForPrincipalsVersionOrigin(cx, obj,
|
||||||
|
principals, originPrincipals,
|
||||||
|
chars, nchars,
|
||||||
|
filename, lineno, version);
|
||||||
|
free(chars);
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T *
|
||||||
|
FreezeThawImpl(JSContext *cx, T *thing, JSBool (*xdrAction)(JSXDRState *xdr, T **))
|
||||||
|
{
|
||||||
|
// freeze
|
||||||
|
JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
||||||
|
if (!w)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
void *memory = NULL;
|
||||||
|
uint32_t nbytes;
|
||||||
|
if (xdrAction(w, &thing)) {
|
||||||
|
void *p = JS_XDRMemGetData(w, &nbytes);
|
||||||
|
if (p) {
|
||||||
|
memory = JS_malloc(cx, nbytes);
|
||||||
|
if (memory)
|
||||||
|
memcpy(memory, p, nbytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS_XDRDestroy(w);
|
||||||
|
if (!memory)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// thaw
|
||||||
|
JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
|
||||||
|
JS_XDRMemSetData(r, memory, nbytes);
|
||||||
|
if (!xdrAction(r, &thing))
|
||||||
|
thing = NULL;
|
||||||
|
JS_XDRDestroy(r); // this frees `memory
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSScript *
|
||||||
|
FreezeThaw(JSContext *cx, JSScript *script)
|
||||||
|
{
|
||||||
|
return FreezeThawImpl(cx, script, JS_XDRScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSObject *
|
||||||
|
FreezeThaw(JSContext *cx, JSObject *funobj)
|
||||||
|
{
|
||||||
|
return FreezeThawImpl(cx, funobj, JS_XDRFunctionObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
SubsumePrincipals(JSPrincipals *, JSPrincipals *)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSPrincipals testPrincipals[] = {
|
||||||
|
{ const_cast<char *>("foo.bar"), 1, NULL, SubsumePrincipals },
|
||||||
|
{ const_cast<char *>("dot.com"), 1, NULL, SubsumePrincipals },
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp)
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
|
JSPrincipals *p = *principalsp;
|
||||||
|
for (index = 0; ; ++index) {
|
||||||
|
if (index == mozilla::ArrayLength(testPrincipals))
|
||||||
|
return false;
|
||||||
|
if (p == &testPrincipals[index])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_XDRUint32(xdr, &index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
|
if (index >= mozilla::ArrayLength(testPrincipals))
|
||||||
|
return false;
|
||||||
|
*principalsp = &testPrincipals[index];
|
||||||
|
JSPRINCIPALS_HOLD(xdr->cx, *principalsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_TEST(testXDR_principals)
|
||||||
|
{
|
||||||
|
static JSSecurityCallbacks seccb = {
|
||||||
|
CheckAccess,
|
||||||
|
TranscodePrincipals,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_SetRuntimeSecurityCallbacks(rt, &seccb);
|
||||||
|
|
||||||
|
JSScript *script;
|
||||||
|
for (int i = TEST_FIRST; i != TEST_END; ++i) {
|
||||||
|
script = createScriptViaXDR(NULL, NULL, i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(!JS_GetScriptPrincipals(cx, script));
|
||||||
|
CHECK(!JS_GetScriptOriginPrincipals(cx, script));
|
||||||
|
|
||||||
|
script = createScriptViaXDR(NULL, NULL, i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(!JS_GetScriptPrincipals(cx, script));
|
||||||
|
CHECK(!JS_GetScriptOriginPrincipals(cx, script));
|
||||||
|
|
||||||
|
script = createScriptViaXDR(&testPrincipals[0], NULL, i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
|
||||||
|
CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[0]);
|
||||||
|
|
||||||
|
script = createScriptViaXDR(&testPrincipals[0], &testPrincipals[0], i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
|
||||||
|
CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[0]);
|
||||||
|
|
||||||
|
script = createScriptViaXDR(&testPrincipals[0], &testPrincipals[1], i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(JS_GetScriptPrincipals(cx, script) == &testPrincipals[0]);
|
||||||
|
CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[1]);
|
||||||
|
|
||||||
|
script = createScriptViaXDR(NULL, &testPrincipals[1], i);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(!JS_GetScriptPrincipals(cx, script));
|
||||||
|
CHECK(JS_GetScriptOriginPrincipals(cx, script) == &testPrincipals[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TestCase {
|
||||||
|
TEST_FIRST,
|
||||||
|
TEST_SCRIPT = TEST_FIRST,
|
||||||
|
TEST_FUNCTION,
|
||||||
|
TEST_SERIALIZED_FUNCTION,
|
||||||
|
TEST_END
|
||||||
|
};
|
||||||
|
|
||||||
|
JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
|
||||||
|
{
|
||||||
|
const char src[] =
|
||||||
|
"function f() { return 1; }\n"
|
||||||
|
"f;\n";
|
||||||
|
|
||||||
|
JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
|
||||||
|
src, strlen(src), "test", 1,
|
||||||
|
JSVERSION_DEFAULT);
|
||||||
|
if (!script)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
|
||||||
|
script = FreezeThaw(cx, script);
|
||||||
|
if (!script)
|
||||||
|
return NULL;
|
||||||
|
if (testCase == TEST_SCRIPT)
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Value v;
|
||||||
|
JSBool ok = JS_ExecuteScript(cx, global, script, &v);
|
||||||
|
if (!ok || !v.isObject())
|
||||||
|
return NULL;
|
||||||
|
JSObject *funobj = &v.toObject();
|
||||||
|
if (testCase == TEST_FUNCTION) {
|
||||||
|
funobj = FreezeThaw(cx, funobj);
|
||||||
|
if (!funobj)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
|
||||||
|
}
|
||||||
|
|
||||||
|
END_TEST(testXDR_principals)
|
||||||
|
|
||||||
|
BEGIN_TEST(testXDR_atline)
|
||||||
|
{
|
||||||
|
JS_ToggleOptions(cx, JSOPTION_ATLINE);
|
||||||
|
CHECK(JS_GetOptions(cx) & JSOPTION_ATLINE);
|
||||||
|
|
||||||
|
const char src[] =
|
||||||
|
"//@line 100 \"foo\"\n"
|
||||||
|
"function nested() { }\n"
|
||||||
|
"//@line 200 \"bar\"\n"
|
||||||
|
"nested;\n";
|
||||||
|
|
||||||
|
JSScript *script = JS_CompileScript(cx, global, src, strlen(src), "internal", 1);
|
||||||
|
CHECK(script);
|
||||||
|
CHECK(script = FreezeThaw(cx, script));
|
||||||
|
CHECK(!strcmp("bar", JS_GetScriptFilename(cx, script)));
|
||||||
|
|
||||||
|
JS::Value v;
|
||||||
|
JSBool ok = JS_ExecuteScript(cx, global, script, &v);
|
||||||
|
CHECK(ok);
|
||||||
|
CHECK(v.isObject());
|
||||||
|
|
||||||
|
JSObject *funobj = &v.toObject();
|
||||||
|
script = JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
|
||||||
|
CHECK(!strcmp("foo", JS_GetScriptFilename(cx, script)));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_TEST(testXDR_atline)
|
||||||
|
|
||||||
BEGIN_TEST(testXDR_bug506491)
|
BEGIN_TEST(testXDR_bug506491)
|
||||||
{
|
{
|
||||||
const char *s =
|
const char *s =
|
||||||
@ -19,24 +249,8 @@ BEGIN_TEST(testXDR_bug506491)
|
|||||||
JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
|
JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
|
||||||
CHECK(script);
|
CHECK(script);
|
||||||
|
|
||||||
// freeze
|
script = FreezeThaw(cx, script);
|
||||||
JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
CHECK(script);
|
||||||
CHECK(w);
|
|
||||||
CHECK(JS_XDRScript(w, &script));
|
|
||||||
uint32_t nbytes;
|
|
||||||
void *p = JS_XDRMemGetData(w, &nbytes);
|
|
||||||
CHECK(p);
|
|
||||||
void *frozen = JS_malloc(cx, nbytes);
|
|
||||||
CHECK(frozen);
|
|
||||||
js_memcpy(frozen, p, nbytes);
|
|
||||||
JS_XDRDestroy(w);
|
|
||||||
|
|
||||||
// thaw
|
|
||||||
script = NULL;
|
|
||||||
JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
|
|
||||||
JS_XDRMemSetData(r, frozen, nbytes);
|
|
||||||
CHECK(JS_XDRScript(r, &script));
|
|
||||||
JS_XDRDestroy(r); // this frees `frozen`
|
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
jsvalRoot v2(cx);
|
jsvalRoot v2(cx);
|
||||||
@ -59,24 +273,8 @@ BEGIN_TEST(testXDR_bug516827)
|
|||||||
JSScript *script = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
|
JSScript *script = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
|
||||||
CHECK(script);
|
CHECK(script);
|
||||||
|
|
||||||
// freeze
|
script = FreezeThaw(cx, script);
|
||||||
JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
|
CHECK(script);
|
||||||
CHECK(w);
|
|
||||||
CHECK(JS_XDRScript(w, &script));
|
|
||||||
uint32_t nbytes;
|
|
||||||
void *p = JS_XDRMemGetData(w, &nbytes);
|
|
||||||
CHECK(p);
|
|
||||||
void *frozen = JS_malloc(cx, nbytes);
|
|
||||||
CHECK(frozen);
|
|
||||||
js_memcpy(frozen, p, nbytes);
|
|
||||||
JS_XDRDestroy(w);
|
|
||||||
|
|
||||||
// thaw
|
|
||||||
script = NULL;
|
|
||||||
JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
|
|
||||||
JS_XDRMemSetData(r, frozen, nbytes);
|
|
||||||
CHECK(JS_XDRScript(r, &script));
|
|
||||||
JS_XDRDestroy(r); // this frees `frozen`
|
|
||||||
|
|
||||||
// execute with null result meaning no result wanted
|
// execute with null result meaning no result wanted
|
||||||
CHECK(JS_ExecuteScript(cx, global, script, NULL));
|
CHECK(JS_ExecuteScript(cx, global, script, NULL));
|
||||||
|
@ -4835,7 +4835,8 @@ JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JSScript *
|
static JSScript *
|
||||||
CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *principals,
|
CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
|
||||||
|
JSPrincipals *principals, JSPrincipals *originPrincipals,
|
||||||
const jschar *chars, size_t length,
|
const jschar *chars, size_t length,
|
||||||
const char *filename, uintN lineno, JSVersion version)
|
const char *filename, uintN lineno, JSVersion version)
|
||||||
{
|
{
|
||||||
@ -4846,7 +4847,7 @@ CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *p
|
|||||||
AutoLastFrameCheck lfc(cx);
|
AutoLastFrameCheck lfc(cx);
|
||||||
|
|
||||||
uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
|
uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
|
||||||
return frontend::CompileScript(cx, obj, NULL, principals, NULL, tcflags,
|
return frontend::CompileScript(cx, obj, NULL, principals, originPrincipals, tcflags,
|
||||||
chars, length, filename, lineno, version);
|
chars, length, filename, lineno, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4858,8 +4859,21 @@ JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
|||||||
JSVersion version)
|
JSVersion version)
|
||||||
{
|
{
|
||||||
AutoVersionAPI avi(cx, version);
|
AutoVersionAPI avi(cx, version);
|
||||||
return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
|
return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
|
||||||
avi.version());
|
filename, lineno, avi.version());
|
||||||
|
}
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(JSScript *)
|
||||||
|
JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
||||||
|
JSPrincipals *principals,
|
||||||
|
JSPrincipals *originPrincipals,
|
||||||
|
const jschar *chars, size_t length,
|
||||||
|
const char *filename, uintN lineno,
|
||||||
|
JSVersion version)
|
||||||
|
{
|
||||||
|
AutoVersionAPI avi(cx, version);
|
||||||
|
return CompileUCScriptForPrincipalsCommon(cx, obj, principals, originPrincipals,
|
||||||
|
chars, length, filename, lineno, avi.version());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSScript *)
|
JS_PUBLIC_API(JSScript *)
|
||||||
@ -4867,8 +4881,8 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *prin
|
|||||||
const jschar *chars, size_t length,
|
const jschar *chars, size_t length,
|
||||||
const char *filename, uintN lineno)
|
const char *filename, uintN lineno)
|
||||||
{
|
{
|
||||||
return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
|
return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
|
||||||
cx->findVersion());
|
filename, lineno, cx->findVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSScript *)
|
JS_PUBLIC_API(JSScript *)
|
||||||
|
@ -4258,6 +4258,17 @@ JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
|||||||
const jschar *chars, size_t length,
|
const jschar *chars, size_t length,
|
||||||
const char *filename, uintN lineno,
|
const char *filename, uintN lineno,
|
||||||
JSVersion version);
|
JSVersion version);
|
||||||
|
/*
|
||||||
|
* If originPrincipals is null, then the value of principals is used as origin
|
||||||
|
* principals for the compiled script.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(JSScript *)
|
||||||
|
JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
||||||
|
JSPrincipals *principals,
|
||||||
|
JSPrincipals *originPrincipals,
|
||||||
|
const jschar *chars, size_t length,
|
||||||
|
const char *filename, uintN lineno,
|
||||||
|
JSVersion version);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSScript *)
|
extern JS_PUBLIC_API(JSScript *)
|
||||||
JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename);
|
JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename);
|
||||||
@ -4422,7 +4433,8 @@ JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
|||||||
* A script's originPrincipals may be retrieved through the debug API (via
|
* A script's originPrincipals may be retrieved through the debug API (via
|
||||||
* JS_GetScriptOriginPrincipals) and the originPrincipals are transitively
|
* JS_GetScriptOriginPrincipals) and the originPrincipals are transitively
|
||||||
* assigned to any nested scripts (including scripts dynamically created via
|
* assigned to any nested scripts (including scripts dynamically created via
|
||||||
* eval and the Function constructor).
|
* eval and the Function constructor). If originPrincipals is null, then the
|
||||||
|
* value of principals is used as origin principals for the script.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
|
||||||
|
@ -441,7 +441,9 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
SavedCallerFun,
|
SavedCallerFun,
|
||||||
StrictModeCode,
|
StrictModeCode,
|
||||||
UsesEval,
|
UsesEval,
|
||||||
UsesArguments
|
UsesArguments,
|
||||||
|
OwnFilename,
|
||||||
|
SharedFilename
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t length, lineno, nslots;
|
uint32_t length, lineno, nslots;
|
||||||
@ -449,17 +451,12 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
uint32_t prologLength, version, encodedClosedCount;
|
uint32_t prologLength, version, encodedClosedCount;
|
||||||
uint16_t nClosedArgs = 0, nClosedVars = 0;
|
uint16_t nClosedArgs = 0, nClosedVars = 0;
|
||||||
uint32_t nTypeSets = 0;
|
uint32_t nTypeSets = 0;
|
||||||
uint32_t encodeable, sameOriginPrincipals;
|
|
||||||
JSSecurityCallbacks *callbacks;
|
|
||||||
uint32_t scriptBits = 0;
|
uint32_t scriptBits = 0;
|
||||||
|
|
||||||
JSContext *cx = xdr->cx;
|
JSContext *cx = xdr->cx;
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
||||||
jssrcnote *notes = NULL;
|
jssrcnote *notes = NULL;
|
||||||
XDRScriptState *state = xdr->state;
|
|
||||||
|
|
||||||
JS_ASSERT(state);
|
|
||||||
|
|
||||||
/* XDR arguments, local vars, and upvars. */
|
/* XDR arguments, local vars, and upvars. */
|
||||||
uint16_t nargs, nvars, nupvars;
|
uint16_t nargs, nvars, nupvars;
|
||||||
@ -611,6 +608,12 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
scriptBits |= (1 << UsesEval);
|
scriptBits |= (1 << UsesEval);
|
||||||
if (script->usesArguments)
|
if (script->usesArguments)
|
||||||
scriptBits |= (1 << UsesArguments);
|
scriptBits |= (1 << UsesArguments);
|
||||||
|
if (script->filename) {
|
||||||
|
scriptBits |= (script->filename != xdr->sharedFilename)
|
||||||
|
? (1 << OwnFilename)
|
||||||
|
: (1 << SharedFilename);
|
||||||
|
}
|
||||||
|
|
||||||
JS_ASSERT(!script->compileAndGo);
|
JS_ASSERT(!script->compileAndGo);
|
||||||
JS_ASSERT(!script->hasSingletons);
|
JS_ASSERT(!script->hasSingletons);
|
||||||
}
|
}
|
||||||
@ -686,52 +689,39 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE && state->filename) {
|
if (scriptBits & (1 << OwnFilename)) {
|
||||||
if (!state->filenameSaved) {
|
char *filename;
|
||||||
const char *filename = state->filename;
|
if (xdr->mode == JSXDR_ENCODE)
|
||||||
filename = SaveScriptFilename(xdr->cx, filename);
|
filename = const_cast<char *>(script->filename);
|
||||||
xdr->cx->free_((void *) state->filename);
|
if (!JS_XDRCString(xdr, &filename))
|
||||||
state->filename = filename;
|
return false;
|
||||||
state->filenameSaved = true;
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
if (!filename)
|
script->filename = SaveScriptFilename(xdr->cx, filename);
|
||||||
|
Foreground::free_(filename);
|
||||||
|
if (!script->filename)
|
||||||
return false;
|
return false;
|
||||||
|
if (!xdr->sharedFilename)
|
||||||
|
xdr->sharedFilename = script->filename;
|
||||||
}
|
}
|
||||||
script->filename = state->filename;
|
} else if (scriptBits & (1 << SharedFilename)) {
|
||||||
|
JS_ASSERT(xdr->sharedFilename);
|
||||||
|
if (xdr->mode == JSXDR_DECODE)
|
||||||
|
script->filename = xdr->sharedFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT_IF(xdr->mode == JSXDR_ENCODE, state->filename == script->filename);
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
|
JS_ASSERT(!script->principals);
|
||||||
|
JS_ASSERT(!script->originPrincipals);
|
||||||
|
|
||||||
callbacks = JS_GetSecurityCallbacks(cx);
|
/* The origin principals must be normalized at this point. */
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
JS_ASSERT_IF(script->principals, script->originPrincipals);
|
||||||
encodeable = script->principals && callbacks && callbacks->principalsTranscoder;
|
if (xdr->principals) {
|
||||||
|
script->principals = xdr->principals;
|
||||||
if (!JS_XDRUint32(xdr, &encodeable))
|
JSPRINCIPALS_HOLD(cx, xdr->principals);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (encodeable) {
|
|
||||||
if (!callbacks || !callbacks->principalsTranscoder) {
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_CANT_DECODE_PRINCIPALS);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (xdr->originPrincipals) {
|
||||||
if (!callbacks->principalsTranscoder(xdr, &script->principals))
|
script->originPrincipals = xdr->originPrincipals;
|
||||||
return false;
|
JSPRINCIPALS_HOLD(cx, xdr->originPrincipals);
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
|
||||||
sameOriginPrincipals = script->principals == script->originPrincipals;
|
|
||||||
|
|
||||||
if (!JS_XDRUint32(xdr, &sameOriginPrincipals))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (sameOriginPrincipals) {
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
|
||||||
script->originPrincipals = script->principals;
|
|
||||||
JSPRINCIPALS_HOLD(cx, script->originPrincipals);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!callbacks->principalsTranscoder(xdr, &script->originPrincipals))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,29 +1707,8 @@ CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, uintN *linenop
|
|||||||
*origin = script->originPrincipals;
|
*origin = script->originPrincipals;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DisablePrincipalsTranscoding {
|
|
||||||
JSSecurityCallbacks *callbacks;
|
|
||||||
JSPrincipalsTranscoder temp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DisablePrincipalsTranscoding(JSContext *cx)
|
|
||||||
: callbacks(JS_GetRuntimeSecurityCallbacks(cx->runtime)),
|
|
||||||
temp(NULL)
|
|
||||||
{
|
|
||||||
if (callbacks) {
|
|
||||||
temp = callbacks->principalsTranscoder;
|
|
||||||
callbacks->principalsTranscoder = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~DisablePrincipalsTranscoding() {
|
|
||||||
if (callbacks)
|
|
||||||
callbacks->principalsTranscoder = temp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AutoJSXDRState {
|
class AutoJSXDRState {
|
||||||
public:
|
public:
|
||||||
AutoJSXDRState(JSXDRState *x
|
AutoJSXDRState(JSXDRState *x
|
||||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
: xdr(x)
|
: xdr(x)
|
||||||
@ -1756,7 +1725,12 @@ public:
|
|||||||
return xdr;
|
return xdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
JSXDRState* operator->() const
|
||||||
|
{
|
||||||
|
return xdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
JSXDRState *const xdr;
|
JSXDRState *const xdr;
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
@ -1766,18 +1740,11 @@ CloneScript(JSContext *cx, JSScript *script)
|
|||||||
{
|
{
|
||||||
JS_ASSERT(cx->compartment != script->compartment());
|
JS_ASSERT(cx->compartment != script->compartment());
|
||||||
|
|
||||||
// serialize script
|
/* Serialize script. */
|
||||||
AutoJSXDRState w(JS_XDRNewMem(cx, JSXDR_ENCODE));
|
AutoJSXDRState w(JS_XDRNewMem(cx, JSXDR_ENCODE));
|
||||||
if (!w)
|
if (!w)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// we don't want gecko to transcribe our principals for us
|
|
||||||
DisablePrincipalsTranscoding disable(cx);
|
|
||||||
|
|
||||||
XDRScriptState wstate(w);
|
|
||||||
#ifdef DEBUG
|
|
||||||
wstate.filename = script->filename;
|
|
||||||
#endif
|
|
||||||
if (!XDRScript(w, &script))
|
if (!XDRScript(w, &script))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -1786,35 +1753,25 @@ CloneScript(JSContext *cx, JSScript *script)
|
|||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// de-serialize script
|
/* De-serialize script. */
|
||||||
AutoJSXDRState r(JS_XDRNewMem(cx, JSXDR_DECODE));
|
AutoJSXDRState r(JS_XDRNewMem(cx, JSXDR_DECODE));
|
||||||
if (!r)
|
if (!r)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Hand p off from w to r. Don't want them to share the data
|
/*
|
||||||
// mem, lest they both try to free it in JS_XDRDestroy
|
* Hand p off from w to r. Don't want them to share the data mem, lest
|
||||||
|
* they both try to free it in JS_XDRDestroy.
|
||||||
|
*/
|
||||||
JS_XDRMemSetData(r, p, nbytes);
|
JS_XDRMemSetData(r, p, nbytes);
|
||||||
JS_XDRMemSetData(w, NULL, 0);
|
JS_XDRMemSetData(w, NULL, 0);
|
||||||
|
|
||||||
XDRScriptState rstate(r);
|
r->principals = cx->compartment->principals;
|
||||||
rstate.filename = script->filename;
|
r->originPrincipals = JSScript::normalizeOriginPrincipals(cx->compartment->principals,
|
||||||
rstate.filenameSaved = true;
|
script->originPrincipals);
|
||||||
|
|
||||||
JSScript *newScript = NULL;
|
JSScript *newScript = NULL;
|
||||||
if (!XDRScript(r, &newScript))
|
if (!XDRScript(r, &newScript))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// set the proper principals for the script's new compartment
|
|
||||||
// the originPrincipals are not related to compartment, so just copy
|
|
||||||
newScript->principals = newScript->compartment()->principals;
|
|
||||||
newScript->originPrincipals = script->originPrincipals;
|
|
||||||
if (!newScript->originPrincipals)
|
|
||||||
newScript->originPrincipals = newScript->principals;
|
|
||||||
if (newScript->principals) {
|
|
||||||
JSPRINCIPALS_HOLD(cx, newScript->principals);
|
|
||||||
JSPRINCIPALS_HOLD(cx, newScript->originPrincipals);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newScript;
|
return newScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +672,7 @@ struct JSScript : public js::gc::Cell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* computedSizeOfData() is the in-use size of all the data sections.
|
* computedSizeOfData() is the in-use size of all the data sections.
|
||||||
* sizeOfData() is the size of the block allocated to hold all the data sections
|
* sizeOfData() is the size of the block allocated to hold all the data sections
|
||||||
* (which can be larger than the in-use size).
|
* (which can be larger than the in-use size).
|
||||||
*/
|
*/
|
||||||
@ -829,6 +829,11 @@ struct JSScript : public js::gc::Cell {
|
|||||||
static inline void writeBarrierPost(JSScript *script, void *addr);
|
static inline void writeBarrierPost(JSScript *script, void *addr);
|
||||||
|
|
||||||
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
|
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
|
||||||
|
|
||||||
|
static JSPrincipals *normalizeOriginPrincipals(JSPrincipals *principals,
|
||||||
|
JSPrincipals *originPrincipals) {
|
||||||
|
return originPrincipals ? originPrincipals : principals;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* If this fails, padding_ can be removed. */
|
/* If this fails, padding_ can be removed. */
|
||||||
@ -932,7 +937,7 @@ extern JSScript *
|
|||||||
CloneScript(JSContext *cx, JSScript *script);
|
CloneScript(JSContext *cx, JSScript *script);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: after a successful JSXDR_DECODE, js_XDRScript callers must do any
|
* NB: after a successful JSXDR_DECODE, XDRScript callers must do any
|
||||||
* required subsequent set-up of owning function or script object and then call
|
* required subsequent set-up of owning function or script object and then call
|
||||||
* js_CallNewScriptHook.
|
* js_CallNewScriptHook.
|
||||||
*/
|
*/
|
||||||
|
@ -237,7 +237,9 @@ JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
|
|||||||
xdr->mode = mode;
|
xdr->mode = mode;
|
||||||
xdr->cx = cx;
|
xdr->cx = cx;
|
||||||
xdr->userdata = NULL;
|
xdr->userdata = NULL;
|
||||||
xdr->state = NULL;
|
xdr->sharedFilename = NULL;
|
||||||
|
xdr->principals = NULL;
|
||||||
|
xdr->originPrincipals = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSXDRState *)
|
JS_PUBLIC_API(JSXDRState *)
|
||||||
@ -394,19 +396,6 @@ JS_XDRCString(JSXDRState *xdr, char **sp)
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
|
|
||||||
{
|
|
||||||
uint32_t null = (*sp == NULL);
|
|
||||||
if (!JS_XDRUint32(xdr, &null))
|
|
||||||
return JS_FALSE;
|
|
||||||
if (null) {
|
|
||||||
*sp = NULL;
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
return JS_XDRCString(xdr, sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
XDRChars(JSXDRState *xdr, jschar *chars, uint32_t nchars)
|
XDRChars(JSXDRState *xdr, jschar *chars, uint32_t nchars)
|
||||||
{
|
{
|
||||||
@ -543,44 +532,100 @@ js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
XDRScriptState::XDRScriptState(JSXDRState *x)
|
static bool
|
||||||
: xdr(x)
|
XDRPrincipals(JSXDRState *xdr)
|
||||||
, filename(NULL)
|
|
||||||
, filenameSaved(false)
|
|
||||||
{
|
{
|
||||||
JS_ASSERT(!xdr->state);
|
const uint8_t HAS_PRINCIPALS = 1;
|
||||||
|
const uint8_t HAS_ORIGIN = 2;
|
||||||
|
|
||||||
xdr->state = this;
|
uint8_t flags = 0;
|
||||||
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
|
if (xdr->principals)
|
||||||
|
flags |= HAS_PRINCIPALS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the common case when principals == originPrincipals we want to
|
||||||
|
* avoid serializing the same principal twice. As originPrincipals are
|
||||||
|
* normalized and principals imply originPrincipals we simply set
|
||||||
|
* HAS_ORIGIN only if originPrincipals is set and different from
|
||||||
|
* principals. During decoding we re-normalize originPrincipals.
|
||||||
|
*/
|
||||||
|
JS_ASSERT_IF(xdr->principals, xdr->originPrincipals);
|
||||||
|
if (xdr->originPrincipals && xdr->originPrincipals != xdr->principals)
|
||||||
|
flags |= HAS_ORIGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_XDRUint8(xdr, &flags))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (flags & (HAS_PRINCIPALS | HAS_ORIGIN)) {
|
||||||
|
JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx);
|
||||||
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
|
if (!scb || !scb->principalsTranscoder) {
|
||||||
|
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_CANT_DECODE_PRINCIPALS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
JS_ASSERT(scb);
|
||||||
|
JS_ASSERT(scb->principalsTranscoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & HAS_PRINCIPALS) {
|
||||||
|
if (!scb->principalsTranscoder(xdr, &xdr->principals))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & HAS_ORIGIN) {
|
||||||
|
if (!scb->principalsTranscoder(xdr, &xdr->originPrincipals))
|
||||||
|
return false;
|
||||||
|
} else if (xdr->mode == JSXDR_DECODE && xdr->principals) {
|
||||||
|
xdr->originPrincipals = xdr->principals;
|
||||||
|
JSPRINCIPALS_HOLD(xdr->cx, xdr->principals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
XDRScriptState::~XDRScriptState()
|
namespace {
|
||||||
{
|
|
||||||
xdr->state = NULL;
|
struct AutoDropXDRPrincipals {
|
||||||
if (xdr->mode == JSXDR_DECODE && filename && !filenameSaved)
|
JSXDRState *const xdr;
|
||||||
xdr->cx->free_((void *)filename);
|
|
||||||
}
|
AutoDropXDRPrincipals(JSXDRState *xdr)
|
||||||
|
: xdr(xdr) { }
|
||||||
|
|
||||||
|
~AutoDropXDRPrincipals() {
|
||||||
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
|
if (xdr->principals)
|
||||||
|
JSPRINCIPALS_DROP(xdr->cx, xdr->principals);
|
||||||
|
if (xdr->originPrincipals)
|
||||||
|
JSPRINCIPALS_DROP(xdr->cx, xdr->originPrincipals);
|
||||||
|
}
|
||||||
|
xdr->principals = NULL;
|
||||||
|
xdr->originPrincipals = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace anonymous */
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
|
||||||
{
|
{
|
||||||
XDRScriptState fstate(xdr);
|
AutoDropXDRPrincipals drop(xdr);
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_ENCODE) {
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
JSFunction* fun = (*objp)->toFunction();
|
JSScript *script = (*objp)->toFunction()->script();
|
||||||
fstate.filename = fun->script()->filename;
|
xdr->principals = script->principals;
|
||||||
|
xdr->originPrincipals = script->originPrincipals;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_XDRCStringOrNull(xdr, (char **) &fstate.filename))
|
return XDRPrincipals(xdr) && XDRFunctionObject(xdr, objp);
|
||||||
return false;
|
|
||||||
|
|
||||||
return XDRFunctionObject(xdr, objp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!xdr->state);
|
|
||||||
|
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t bytecodeVer;
|
uint32_t bytecodeVer;
|
||||||
@ -605,17 +650,16 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
XDRScriptState state(xdr);
|
{
|
||||||
if (!xdr->state)
|
AutoDropXDRPrincipals drop(xdr);
|
||||||
return false;
|
if (xdr->mode == JSXDR_ENCODE) {
|
||||||
|
xdr->principals = script->principals;
|
||||||
if (xdr->mode == JSXDR_ENCODE)
|
xdr->originPrincipals = script->originPrincipals;
|
||||||
state.filename = script->filename;
|
}
|
||||||
if (!JS_XDRCStringOrNull(xdr, (char **) &state.filename))
|
|
||||||
return false;
|
if (!XDRPrincipals(xdr) || !XDRScript(xdr, &script))
|
||||||
|
return false;
|
||||||
if (!XDRScript(xdr, &script))
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (xdr->mode == JSXDR_DECODE) {
|
||||||
JS_ASSERT(!script->compileAndGo);
|
JS_ASSERT(!script->compileAndGo);
|
||||||
|
@ -105,28 +105,14 @@ typedef struct JSXDROps {
|
|||||||
void (*finalize)(JSXDRState *);
|
void (*finalize)(JSXDRState *);
|
||||||
} JSXDROps;
|
} JSXDROps;
|
||||||
|
|
||||||
struct JSXDRState;
|
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
class XDRScriptState {
|
|
||||||
public:
|
|
||||||
XDRScriptState(JSXDRState *x);
|
|
||||||
~XDRScriptState();
|
|
||||||
|
|
||||||
JSXDRState *xdr;
|
|
||||||
const char *filename;
|
|
||||||
bool filenameSaved;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace JS */
|
|
||||||
|
|
||||||
struct JSXDRState {
|
struct JSXDRState {
|
||||||
JSXDRMode mode;
|
JSXDRMode mode;
|
||||||
JSXDROps *ops;
|
JSXDROps *ops;
|
||||||
JSContext *cx;
|
JSContext *cx;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
js::XDRScriptState *state;
|
const char *sharedFilename;
|
||||||
|
JSPrincipals *principals;
|
||||||
|
JSPrincipals *originPrincipals;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
@ -165,9 +151,6 @@ JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len);
|
|||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRCString(JSXDRState *xdr, char **sp);
|
JS_XDRCString(JSXDRState *xdr, char **sp);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
|
||||||
JS_XDRCStringOrNull(JSXDRState *xdr, char **sp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_XDRString(JSXDRState *xdr, JSString **strp);
|
JS_XDRString(JSXDRState *xdr, JSString **strp);
|
||||||
|
|
||||||
@ -209,7 +192,9 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
|||||||
* and saved versions. If deserialization fails, the data should be
|
* and saved versions. If deserialization fails, the data should be
|
||||||
* invalidated if possible.
|
* invalidated if possible.
|
||||||
*/
|
*/
|
||||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 107)
|
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 108)
|
||||||
|
|
||||||
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Library-private functions.
|
* Library-private functions.
|
||||||
@ -217,6 +202,14 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
|
|||||||
extern JSBool
|
extern JSBool
|
||||||
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
|
js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
/*
|
||||||
|
* Set principals that should be assigned to decoded scripts and functions.
|
||||||
|
* The principals is not held via JS_HoldPrincipals/JS_DropPrincipals unless
|
||||||
|
* they are stored in a decoded script. Thus the caller must either ensure
|
||||||
|
* that principal outlive the XDR instance or are explicitly set to NULL
|
||||||
|
* before they release by the caller.
|
||||||
|
*/
|
||||||
|
extern void
|
||||||
|
js_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals);
|
||||||
|
|
||||||
#endif /* ! jsxdrapi_h___ */
|
#endif /* ! jsxdrapi_h___ */
|
||||||
|
Loading…
Reference in New Issue
Block a user