Bug 1070131 - Stop XDR-serializing origin principals. r=luke,r=bz

This commit is contained in:
Bobby Holley 2014-09-29 10:44:30 +02:00
Родитель c4922ac2f8
Коммит 2a1c09c3d0
9 изменённых файлов: 21 добавлений и 176 удалений

Просмотреть файл

@ -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