Bug 1210099 - Fix structured clone of expanded principal (r=bholley)

This commit is contained in:
Bill McCloskey 2016-02-04 15:12:52 -08:00
parent aa01ca391d
commit 97f2ae4d14
4 changed files with 109 additions and 36 deletions

View File

@ -114,7 +114,8 @@ nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader,
if (!(tag == SCTAG_DOM_NULL_PRINCIPAL ||
tag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
tag == SCTAG_DOM_CONTENT_PRINCIPAL)) {
tag == SCTAG_DOM_CONTENT_PRINCIPAL ||
tag == SCTAG_DOM_EXPANDED_PRINCIPAL)) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return false;
}
@ -122,27 +123,38 @@ nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader,
return ReadKnownPrincipalType(aCx, aReader, tag, aOutPrincipals);
}
/* static */ bool
nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
JSPrincipals** aOutPrincipals)
static bool
ReadPrincipalInfo(JSStructuredCloneReader* aReader,
uint32_t aTag,
PrincipalInfo& aInfo)
{
MOZ_ASSERT(aTag == SCTAG_DOM_NULL_PRINCIPAL ||
aTag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
aTag == SCTAG_DOM_CONTENT_PRINCIPAL);
if (NS_WARN_IF(!NS_IsMainThread())) {
xpc::Throw(aCx, NS_ERROR_UNCATCHABLE_EXCEPTION);
return false;
}
PrincipalInfo info;
if (aTag == SCTAG_DOM_SYSTEM_PRINCIPAL) {
info = SystemPrincipalInfo();
aInfo = SystemPrincipalInfo();
} else if (aTag == SCTAG_DOM_NULL_PRINCIPAL) {
info = NullPrincipalInfo();
} else {
aInfo = NullPrincipalInfo();
} else if (aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) {
uint32_t length, unused;
if (!JS_ReadUint32Pair(aReader, &length, &unused)) {
return false;
}
ExpandedPrincipalInfo expanded;
for (uint32_t i = 0; i < length; i++) {
uint32_t tag;
if (!JS_ReadUint32Pair(aReader, &tag, &unused)) {
return false;
}
PrincipalInfo sub;
if (!ReadPrincipalInfo(aReader, tag, sub)) {
return false;
}
expanded.whitelist().AppendElement(sub);
}
aInfo = expanded;
} else if (aTag == SCTAG_DOM_CONTENT_PRINCIPAL) {
uint32_t suffixLength, specLength;
if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) {
return false;
@ -162,7 +174,33 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
PrincipalOriginAttributes attrs;
attrs.PopulateFromSuffix(suffix);
info = ContentPrincipalInfo(attrs, spec);
aInfo = ContentPrincipalInfo(attrs, spec);
} else {
MOZ_CRASH("unexpected principal structured clone tag");
}
return true;
}
/* static */ bool
nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aTag,
JSPrincipals** aOutPrincipals)
{
MOZ_ASSERT(aTag == SCTAG_DOM_NULL_PRINCIPAL ||
aTag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
aTag == SCTAG_DOM_CONTENT_PRINCIPAL ||
aTag == SCTAG_DOM_EXPANDED_PRINCIPAL);
if (NS_WARN_IF(!NS_IsMainThread())) {
xpc::Throw(aCx, NS_ERROR_UNCATCHABLE_EXCEPTION);
return false;
}
PrincipalInfo info;
if (!ReadPrincipalInfo(aReader, aTag, info)) {
return false;
}
nsresult rv;
@ -176,6 +214,40 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
return true;
}
static bool
WritePrincipalInfo(JSStructuredCloneWriter* aWriter, const PrincipalInfo& aInfo)
{
if (aInfo.type() == PrincipalInfo::TNullPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0);
}
if (aInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0);
}
if (aInfo.type() == PrincipalInfo::TExpandedPrincipalInfo) {
const ExpandedPrincipalInfo& expanded = aInfo;
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_EXPANDED_PRINCIPAL, 0) ||
!JS_WriteUint32Pair(aWriter, expanded.whitelist().Length(), 0)) {
return false;
}
for (uint32_t i = 0; i < expanded.whitelist().Length(); i++) {
if (!WritePrincipalInfo(aWriter, expanded.whitelist()[i])) {
return false;
}
}
return true;
}
MOZ_ASSERT(aInfo.type() == PrincipalInfo::TContentPrincipalInfo);
const ContentPrincipalInfo& cInfo = aInfo;
nsAutoCString suffix;
cInfo.attrs().CreateSuffix(suffix);
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) &&
JS_WriteUint32Pair(aWriter, suffix.Length(), cInfo.spec().Length()) &&
JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length());
}
bool
nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter)
{
@ -185,19 +257,5 @@ nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter)
return false;
}
if (info.type() == PrincipalInfo::TNullPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0);
}
if (info.type() == PrincipalInfo::TSystemPrincipalInfo) {
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0);
}
MOZ_ASSERT(info.type() == PrincipalInfo::TContentPrincipalInfo);
const ContentPrincipalInfo& cInfo = info;
nsAutoCString suffix;
cInfo.attrs().CreateSuffix(suffix);
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) &&
JS_WriteUint32Pair(aWriter, suffix.Length(), cInfo.spec().Length()) &&
JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) &&
JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length());
return WritePrincipalInfo(aWriter, info);
}

View File

@ -417,7 +417,8 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
if (aTag == SCTAG_DOM_NULL_PRINCIPAL ||
aTag == SCTAG_DOM_SYSTEM_PRINCIPAL ||
aTag == SCTAG_DOM_CONTENT_PRINCIPAL) {
aTag == SCTAG_DOM_CONTENT_PRINCIPAL ||
aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) {
JSPrincipals* prin;
if (!nsJSPrincipals::ReadKnownPrincipalType(aCx, aReader, aTag, &prin)) {
return nullptr;

View File

@ -51,6 +51,8 @@ enum StructuredCloneTags {
// This tag is for OffscreenCanvas.
SCTAG_DOM_CANVAS,
SCTAG_DOM_EXPANDED_PRINCIPAL,
SCTAG_DOM_MAX
};

View File

@ -47,6 +47,13 @@
(secMan.isSystemPrincipal(message.data) ? "OK" : "KO"));
});
addMessageListener("test:ep", function(message) {
sendAsyncMessage("test:result", "expanded principal: " +
(message.data.isExpandedPrincipal ? "OK" : "KO"));
sendAsyncMessage("test:result", "correct origin: " +
(message.data.origin == "[Expanded Principal [http://bar.example.com, http://foo.example.com]]" ? "OK" : "KO"));
});
addMessageListener("test:null", function(message) {
sendAsyncMessage("test:result", "is nsIPrincipal: " +
(message.data instanceof Ci.nsIPrincipal ? "OK" : "KO"));
@ -65,6 +72,9 @@
iframe.id = "iframe";
iframe.src = childFrameURL;
let sb = new Cu.Sandbox(['http://foo.example.com', 'http://bar.example.com']);
let ep = Components.utils.getObjectPrincipal(sb);
iframe.addEventListener("mozbrowserloadend", function() {
ok(true, "Got iframe load event.");
@ -92,6 +102,8 @@
createInstance(Ci.nsIPrincipal);
mm.sendAsyncMessage("test:system", system);
mm.sendAsyncMessage("test:ep", ep);
let nullP = Cc["@mozilla.org/nullprincipal;1"].
createInstance(Ci.nsIPrincipal);
mm.sendAsyncMessage("test:null", nullP);