mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-31 21:21:08 +00:00
Bug 1070131 - Stop XDR-serializing origin principals. r=luke,r=bz
This commit is contained in:
parent
c4922ac2f8
commit
2a1c09c3d0
@ -12,30 +12,6 @@
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
static JSScript *
|
||||
CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
|
||||
JSPrincipals *originPrincipals,
|
||||
const char *bytes, size_t nbytes,
|
||||
const char *filename, unsigned lineno,
|
||||
JSVersion version)
|
||||
{
|
||||
size_t nchars;
|
||||
if (!JS_DecodeBytes(cx, bytes, nbytes, nullptr, &nchars))
|
||||
return nullptr;
|
||||
char16_t *chars = static_cast<char16_t *>(JS_malloc(cx, nchars * sizeof(char16_t)));
|
||||
if (!chars)
|
||||
return nullptr;
|
||||
JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
|
||||
JS::CompileOptions options(cx);
|
||||
options.setOriginPrincipals(originPrincipals)
|
||||
.setFileAndLine(filename, lineno)
|
||||
.setVersion(version);
|
||||
JS::RootedScript script(cx);
|
||||
JS::Compile(cx, obj, options, chars, nchars, &script);
|
||||
JS_free(cx, chars);
|
||||
return script;
|
||||
}
|
||||
|
||||
static JSScript *
|
||||
FreezeThaw(JSContext *cx, JS::HandleScript script)
|
||||
{
|
||||
@ -46,66 +22,11 @@ FreezeThaw(JSContext *cx, JS::HandleScript script)
|
||||
return nullptr;
|
||||
|
||||
// thaw
|
||||
JSScript *script2 = JS_DecodeScript(cx, memory, nbytes,
|
||||
script->originPrincipals());
|
||||
JSScript *script2 = JS_DecodeScript(cx, memory, nbytes);
|
||||
js_free(memory);
|
||||
return script2;
|
||||
}
|
||||
|
||||
static JSScript *
|
||||
GetScript(JSContext *cx, JS::HandleObject funobj)
|
||||
{
|
||||
JS::RootedFunction fun(cx, JS_GetObjectFunction(funobj));
|
||||
return JS_GetFunctionScript(cx, fun);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
FreezeThaw(JSContext *cx, JS::HandleObject funobj)
|
||||
{
|
||||
// freeze
|
||||
uint32_t nbytes;
|
||||
void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
|
||||
if (!memory)
|
||||
return nullptr;
|
||||
|
||||
// thaw
|
||||
JSScript *script = GetScript(cx, funobj);
|
||||
JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes,
|
||||
script->originPrincipals());
|
||||
js_free(memory);
|
||||
return funobj2;
|
||||
}
|
||||
|
||||
static TestJSPrincipals testPrincipal0(1);
|
||||
static TestJSPrincipals testPrincipal1(1);
|
||||
|
||||
BEGIN_TEST(testXDR_principals)
|
||||
{
|
||||
JSScript *script;
|
||||
JSCompartment *compartment = js::GetContextCompartment(cx);
|
||||
for (int i = TEST_FIRST; i != TEST_END; ++i) {
|
||||
// Appease the new JSAPI assertions. The stuff being tested here is
|
||||
// going away anyway.
|
||||
JS_SetCompartmentPrincipals(compartment, &testPrincipal0);
|
||||
script = createScriptViaXDR(nullptr, i);
|
||||
CHECK(script);
|
||||
CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
|
||||
CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
|
||||
|
||||
script = createScriptViaXDR(&testPrincipal0, i);
|
||||
CHECK(script);
|
||||
CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
|
||||
CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
|
||||
|
||||
script = createScriptViaXDR(&testPrincipal1, i);
|
||||
CHECK(script);
|
||||
CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
|
||||
CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum TestCase {
|
||||
TEST_FIRST,
|
||||
TEST_SCRIPT = TEST_FIRST,
|
||||
@ -114,42 +35,6 @@ enum TestCase {
|
||||
TEST_END
|
||||
};
|
||||
|
||||
JSScript *createScriptViaXDR(JSPrincipals *orig, int testCase)
|
||||
{
|
||||
const char src[] =
|
||||
"function f() { return 1; }\n"
|
||||
"f;\n";
|
||||
|
||||
JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
JS::RootedScript script(cx, CompileScriptForPrincipalsVersionOrigin(cx, global, orig,
|
||||
src, strlen(src), "test", 1,
|
||||
JSVERSION_DEFAULT));
|
||||
if (!script)
|
||||
return nullptr;
|
||||
|
||||
if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
|
||||
script = FreezeThaw(cx, script);
|
||||
if (!script)
|
||||
return nullptr;
|
||||
if (testCase == TEST_SCRIPT)
|
||||
return script;
|
||||
}
|
||||
|
||||
JS::RootedValue v(cx);
|
||||
bool ok = JS_ExecuteScript(cx, global, script, &v);
|
||||
if (!ok || !v.isObject())
|
||||
return nullptr;
|
||||
JS::RootedObject funobj(cx, &v.toObject());
|
||||
if (testCase == TEST_FUNCTION) {
|
||||
funobj = FreezeThaw(cx, funobj);
|
||||
if (!funobj)
|
||||
return nullptr;
|
||||
}
|
||||
return GetScript(cx, funobj);
|
||||
}
|
||||
|
||||
END_TEST(testXDR_principals)
|
||||
|
||||
BEGIN_TEST(testXDR_bug506491)
|
||||
{
|
||||
const char *s =
|
||||
|
@ -6504,10 +6504,9 @@ JS_EncodeInterpretedFunction(JSContext *cx, HandleObject funobjArg, uint32_t *le
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
|
||||
JSPrincipals *originPrincipals)
|
||||
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length)
|
||||
{
|
||||
XDRDecoder decoder(cx, data, length, originPrincipals);
|
||||
XDRDecoder decoder(cx, data, length);
|
||||
RootedScript script(cx);
|
||||
if (!decoder.codeScript(&script))
|
||||
return nullptr;
|
||||
@ -6515,10 +6514,9 @@ JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
|
||||
JSPrincipals *originPrincipals)
|
||||
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length)
|
||||
{
|
||||
XDRDecoder decoder(cx, data, length, originPrincipals);
|
||||
XDRDecoder decoder(cx, data, length);
|
||||
RootedObject funobj(cx);
|
||||
if (!decoder.codeFunction(&funobj))
|
||||
return nullptr;
|
||||
|
@ -5064,11 +5064,10 @@ extern JS_PUBLIC_API(void *)
|
||||
JS_EncodeInterpretedFunction(JSContext *cx, JS::HandleObject funobj, uint32_t *lengthp);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length, JSPrincipals *originPrincipals);
|
||||
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
|
||||
JSPrincipals *originPrincipals);
|
||||
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length);
|
||||
|
||||
namespace JS {
|
||||
|
||||
|
@ -739,7 +739,6 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
* aren't preserved by XDR. So this can be simple.
|
||||
*/
|
||||
CompileOptions options(cx);
|
||||
options.setOriginPrincipals(xdr->originPrincipals());
|
||||
ss->initFromOptions(cx, options);
|
||||
sourceObject = ScriptSourceObject::create(cx, ss);
|
||||
if (!sourceObject ||
|
||||
|
@ -1267,7 +1267,7 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
|
||||
if (loadBytecode) {
|
||||
script = JS_DecodeScript(cx, loadBuffer, loadLength, options.originPrincipals(cx));
|
||||
script = JS_DecodeScript(cx, loadBuffer, loadLength);
|
||||
} else {
|
||||
mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
|
||||
(void) JS::Compile(cx, global, options, chars.start().get(), chars.length(), &script);
|
||||
|
@ -138,12 +138,10 @@ XDRState<mode>::codeConstValue(MutableHandleValue vp)
|
||||
return XDRScriptConst(this, vp);
|
||||
}
|
||||
|
||||
XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,
|
||||
JSPrincipals *originPrincipals)
|
||||
XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length)
|
||||
: XDRState<XDR_DECODE>(cx)
|
||||
{
|
||||
buf.setData(data, length);
|
||||
this->originPrincipals_ = originPrincipals;
|
||||
}
|
||||
|
||||
template class js::XDRState<XDR_ENCODE>;
|
||||
|
@ -28,7 +28,7 @@ namespace js {
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 184);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 185);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
@ -100,10 +100,8 @@ class XDRState {
|
||||
XDRBuffer buf;
|
||||
|
||||
protected:
|
||||
JSPrincipals *originPrincipals_;
|
||||
|
||||
explicit XDRState(JSContext *cx)
|
||||
: buf(cx), originPrincipals_(nullptr) {
|
||||
: buf(cx) {
|
||||
}
|
||||
|
||||
public:
|
||||
@ -111,10 +109,6 @@ class XDRState {
|
||||
return buf.cx();
|
||||
}
|
||||
|
||||
JSPrincipals *originPrincipals() const {
|
||||
return originPrincipals_;
|
||||
}
|
||||
|
||||
bool codeUint8(uint8_t *n) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t *ptr = buf.write(sizeof *n);
|
||||
@ -260,8 +254,7 @@ class XDREncoder : public XDRState<XDR_ENCODE> {
|
||||
|
||||
class XDRDecoder : public XDRState<XDR_DECODE> {
|
||||
public:
|
||||
XDRDecoder(JSContext *cx, const void *data, uint32_t length,
|
||||
JSPrincipals *originPrincipals);
|
||||
XDRDecoder(JSContext *cx, const void *data, uint32_t length);
|
||||
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,7 @@ ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
|
||||
if (NS_FAILED(rv))
|
||||
return rv; // don't warn since NOT_AVAILABLE is an ok error
|
||||
|
||||
scriptp.set(JS_DecodeScript(cx, buf, len, nullptr));
|
||||
scriptp.set(JS_DecodeScript(cx, buf, len));
|
||||
if (!scriptp)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
|
@ -1298,10 +1298,6 @@ nsXPConnect::NotifyDidPaint()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note - We used to have HAS_PRINCIPALS_FLAG = 1 here, so reusing that flag
|
||||
// will require bumping the XDR version number.
|
||||
static const uint8_t HAS_ORIGIN_PRINCIPALS_FLAG = 2;
|
||||
|
||||
static nsresult
|
||||
WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
|
||||
JSScript *scriptArg, HandleObject functionObj)
|
||||
@ -1315,28 +1311,11 @@ WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
|
||||
script.set(JS_GetFunctionScript(cx, fun));
|
||||
}
|
||||
|
||||
nsIPrincipal *principal =
|
||||
nsJSPrincipals::get(JS_GetScriptPrincipals(script));
|
||||
nsIPrincipal *originPrincipal =
|
||||
nsJSPrincipals::get(JS_GetScriptOriginPrincipals(script));
|
||||
|
||||
uint8_t flags = 0;
|
||||
|
||||
// Optimize for the common case when originPrincipals == principals. As
|
||||
// originPrincipals is set to principals when the former is null we can
|
||||
// simply skip the originPrincipals when they are the same as principals.
|
||||
if (originPrincipal && originPrincipal != principal)
|
||||
flags |= HAS_ORIGIN_PRINCIPALS_FLAG;
|
||||
|
||||
uint8_t flags = 0; // We don't have flags anymore.
|
||||
nsresult rv = stream->Write8(flags);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (flags & HAS_ORIGIN_PRINCIPALS_FLAG) {
|
||||
rv = stream->WriteObject(originPrincipal, true);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t size;
|
||||
void* data;
|
||||
@ -1370,16 +1349,11 @@ ReadScriptOrFunction(nsIObjectInputStream *stream, JSContext *cx,
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsJSPrincipals* originPrincipal = nullptr;
|
||||
nsCOMPtr<nsIPrincipal> readOriginPrincipal;
|
||||
if (flags & HAS_ORIGIN_PRINCIPALS_FLAG) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
rv = stream->ReadObject(true, getter_AddRefs(supports));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
readOriginPrincipal = do_QueryInterface(supports);
|
||||
originPrincipal = nsJSPrincipals::get(readOriginPrincipal);
|
||||
}
|
||||
// We don't serialize mutedError-ness of scripts, which is fine as long as
|
||||
// we only serialize system and XUL-y things. We can detect this by checking
|
||||
// where the caller wants us to deserialize.
|
||||
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome() ||
|
||||
CurrentGlobalOrNull(cx) == xpc::CompilationScope());
|
||||
|
||||
uint32_t size;
|
||||
rv = stream->Read32(&size);
|
||||
@ -1393,14 +1367,13 @@ ReadScriptOrFunction(nsIObjectInputStream *stream, JSContext *cx,
|
||||
|
||||
{
|
||||
if (scriptp) {
|
||||
JSScript *script = JS_DecodeScript(cx, data, size, originPrincipal);
|
||||
JSScript *script = JS_DecodeScript(cx, data, size);
|
||||
if (!script)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
*scriptp = script;
|
||||
} else {
|
||||
JSObject *funobj = JS_DecodeInterpretedFunction(cx, data, size,
|
||||
originPrincipal);
|
||||
JSObject *funobj = JS_DecodeInterpretedFunction(cx, data, size);
|
||||
if (!funobj)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user