Bug 1583251 - P3 - Check if it is okay to allow shared memory while deserializing; r=nika,lth

Differential Revision: https://phabricator.services.mozilla.com/D48349

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Tom Tung 2019-10-15 13:42:25 +00:00
Родитель c291baa433
Коммит 5ba65c0735
9 изменённых файлов: 66 добавлений и 25 удалений

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

@ -162,7 +162,6 @@ PostMessageEvent::Run() {
nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
do_QueryObject(targetWindow);
// XXX cloneDataPolicy will be used in P3
JS::CloneDataPolicy cloneDataPolicy;
MOZ_DIAGNOSTIC_ASSERT(targetWindow);
if (mCallerAgentClusterId.isSome() &&
@ -172,8 +171,8 @@ PostMessageEvent::Run() {
StructuredCloneHolder* holder;
if (mHolder.constructed<StructuredCloneHolder>()) {
mHolder.ref<StructuredCloneHolder>().Read(ToSupports(targetWindow), cx,
&messageData, rv);
mHolder.ref<StructuredCloneHolder>().Read(
ToSupports(targetWindow), cx, &messageData, cloneDataPolicy, rv);
holder = &mHolder.ref<StructuredCloneHolder>();
} else {
MOZ_ASSERT(mHolder.constructed<ipc::StructuredCloneData>());

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

@ -190,11 +190,17 @@ bool StructuredCloneHolderBase::Write(JSContext* aCx,
bool StructuredCloneHolderBase::Read(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue) {
return Read(aCx, aValue, JS::CloneDataPolicy());
}
bool StructuredCloneHolderBase::Read(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue,
JS::CloneDataPolicy aCloneDataPolicy) {
MOZ_ASSERT(mBuffer, "Read() without Write() is not allowed.");
MOZ_ASSERT(!mClearCalled, "This method cannot be called after Clear.");
bool ok =
mBuffer->read(aCx, aValue, &StructuredCloneHolder::sCallbacks, this);
bool ok = mBuffer->read(aCx, aValue, aCloneDataPolicy,
&StructuredCloneHolder::sCallbacks, this);
return ok;
}
@ -269,6 +275,13 @@ void StructuredCloneHolder::Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
void StructuredCloneHolder::Read(nsISupports* aParent, JSContext* aCx,
JS::MutableHandle<JS::Value> aValue,
ErrorResult& aRv) {
return Read(aParent, aCx, aValue, JS::CloneDataPolicy(), aRv);
}
void StructuredCloneHolder::Read(nsISupports* aParent, JSContext* aCx,
JS::MutableHandle<JS::Value> aValue,
JS::CloneDataPolicy aCloneDataPolicy,
ErrorResult& aRv) {
MOZ_ASSERT_IF(
mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread,
mCreationEventTarget->IsOnCurrentThread());
@ -277,7 +290,7 @@ void StructuredCloneHolder::Read(nsISupports* aParent, JSContext* aCx,
mozilla::AutoRestore<nsISupports*> guard(mParent);
mParent = aParent;
if (!StructuredCloneHolderBase::Read(aCx, aValue)) {
if (!StructuredCloneHolderBase::Read(aCx, aValue, aCloneDataPolicy)) {
JS_ClearPendingException(aCx);
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
return;
@ -316,8 +329,8 @@ void StructuredCloneHolder::ReadFromBuffer(nsISupports* aParent, JSContext* aCx,
mParent = aParent;
if (!JS_ReadStructuredClone(aCx, aBuffer, aAlgorithmVersion,
mStructuredCloneScope, aValue, &sCallbacks,
this)) {
mStructuredCloneScope, aValue,
JS::CloneDataPolicy(), &sCallbacks, this)) {
JS_ClearPendingException(aCx);
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
}

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

@ -104,6 +104,10 @@ class StructuredCloneHolderBase {
// aValue.
bool Read(JSContext* aCx, JS::MutableHandle<JS::Value> aValue);
// Like Read() but it supports handling of clone policy.
bool Read(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
JS::CloneDataPolicy aCloneDataPolicy);
bool HasData() const { return !!mBuffer; }
JSStructuredCloneData& BufferData() const {
@ -165,6 +169,10 @@ class StructuredCloneHolder : public StructuredCloneHolderBase {
void Read(nsISupports* aParent, JSContext* aCx,
JS::MutableHandle<JS::Value> aValue, ErrorResult& aRv);
void Read(nsISupports* aParent, JSContext* aCx,
JS::MutableHandle<JS::Value> aValue,
JS::CloneDataPolicy aCloneDataPolicy, ErrorResult& aRv);
// Call this method to know if this object is keeping some DOM object alive.
bool HasClonedDOMObjects() const {
return !mBlobImplArray.IsEmpty() || !mWasmModuleArray.IsEmpty() ||

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

@ -1063,7 +1063,7 @@ bool IDBObjectStore::DeserializeValue(JSContext* aCx,
if (!JS_ReadStructuredClone(
aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::DifferentProcessForIndexedDB, aValue,
&callbacks, &aCloneReadInfo)) {
JS::CloneDataPolicy(), &callbacks, &aCloneReadInfo)) {
return false;
}
@ -1222,7 +1222,7 @@ class DeserializeIndexValueHelper final : public Runnable {
if (!JS_ReadStructuredClone(
aCx, mCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::DifferentProcessForIndexedDB, aValue,
&callbacks, &mCloneReadInfo)) {
JS::CloneDataPolicy(), &callbacks, &mCloneReadInfo)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -1328,7 +1328,7 @@ class DeserializeUpgradeValueHelper final : public Runnable {
if (!JS_ReadStructuredClone(
aCx, mCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
JS::StructuredCloneScope::DifferentProcessForIndexedDB, aValue,
&callbacks, &mCloneReadInfo)) {
JS::CloneDataPolicy(), &callbacks, &mCloneReadInfo)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
}

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

@ -543,6 +543,7 @@ class MOZ_NON_MEMMOVABLE JS_PUBLIC_API JSStructuredCloneData {
JS_PUBLIC_API bool JS_ReadStructuredClone(
JSContext* cx, JSStructuredCloneData& data, uint32_t version,
JS::StructuredCloneScope scope, JS::MutableHandleValue vp,
JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure);
/**
@ -632,6 +633,7 @@ class JS_PUBLIC_API JSAutoStructuredCloneBuffer {
}
bool read(JSContext* cx, JS::MutableHandleValue vp,
JS::CloneDataPolicy cloneDataPolicy = JS::CloneDataPolicy(),
const JSStructuredCloneCallbacks* optionalCallbacks = nullptr,
void* closure = nullptr);

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

@ -3498,7 +3498,8 @@ static bool Deserialize(JSContext* cx, unsigned argc, Value* vp) {
RootedValue deserialized(cx);
if (!JS_ReadStructuredClone(cx, *obj->data(), JS_STRUCTURED_CLONE_VERSION,
scope, &deserialized, nullptr, nullptr)) {
scope, &deserialized, JS::CloneDataPolicy(),
nullptr, nullptr)) {
return false;
}
args.rval().set(deserialized);

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

@ -54,9 +54,10 @@ static int testStructuredCloneReaderFuzz(const uint8_t* buf, size_t size) {
return 0;
}
JS::CloneDataPolicy policy;
RootedValue deserialized(gCx);
if (!JS_ReadStructuredClone(gCx, *clonebuf, JS_STRUCTURED_CLONE_VERSION,
scope, &deserialized, nullptr, nullptr)) {
scope, &deserialized, policy, nullptr, nullptr)) {
return 0;
}
@ -70,7 +71,6 @@ static int testStructuredCloneReaderFuzz(const uint8_t* buf, size_t size) {
Tests show that this also doesn't cause a serious performance penalty.
*/
mozilla::Maybe<JSAutoStructuredCloneBuffer> clonebufOut;
JS::CloneDataPolicy policy;
clonebufOut.emplace(scope, nullptr, nullptr);
if (!clonebufOut->write(gCx, deserialized, UndefinedHandleValue, policy)) {

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

@ -137,7 +137,7 @@ bool TestCloneObject() {
JS::RootedValue v1(cx, JS::ObjectValue(*obj1));
CHECK(cloned_buffer.write(cx, v1, nullptr, nullptr));
JS::RootedValue v2(cx);
CHECK(cloned_buffer.read(cx, &v2, nullptr, nullptr));
CHECK(cloned_buffer.read(cx, &v2, JS::CloneDataPolicy(), nullptr, nullptr));
JS::RootedObject obj2(cx, v2.toObjectOrNull());
CHECK(VerifyObject(obj2, 8, 12, false));
@ -173,10 +173,10 @@ bool TestTransferObject() {
JSAutoStructuredCloneBuffer cloned_buffer(
JS::StructuredCloneScope::SameProcessSameThread, nullptr, nullptr);
CHECK(cloned_buffer.write(cx, v1, transferable, JS::CloneDataPolicy(),
nullptr, nullptr));
JS::CloneDataPolicy policy;
CHECK(cloned_buffer.write(cx, v1, transferable, policy, nullptr, nullptr));
JS::RootedValue v2(cx);
CHECK(cloned_buffer.read(cx, &v2, nullptr, nullptr));
CHECK(cloned_buffer.read(cx, &v2, policy, nullptr, nullptr));
JS::RootedObject obj2(cx, v2.toObjectOrNull());
CHECK(VerifyObject(obj2, 8, 12, true));
CHECK(JS::IsDetachedArrayBufferObject(obj1));

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

@ -386,10 +386,12 @@ class SCInput {
struct JSStructuredCloneReader {
public:
explicit JSStructuredCloneReader(SCInput& in, JS::StructuredCloneScope scope,
JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* cb,
void* cbClosure)
: in(in),
allowedScope(scope),
cloneDataPolicy(cloneDataPolicy),
objs(in.context()),
allObjs(in.context()),
callbacks(cb),
@ -430,6 +432,8 @@ struct JSStructuredCloneReader {
// be valid cross-process.)
JS::StructuredCloneScope allowedScope;
const JS::CloneDataPolicy cloneDataPolicy;
// Stack of objects with properties remaining to be read.
RootedValueVector objs;
@ -637,10 +641,11 @@ bool WriteStructuredClone(JSContext* cx, HandleValue v,
bool ReadStructuredClone(JSContext* cx, JSStructuredCloneData& data,
JS::StructuredCloneScope scope, MutableHandleValue vp,
JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* cb,
void* cbClosure) {
SCInput in(cx, data);
JSStructuredCloneReader r(in, scope, cb, cbClosure);
JSStructuredCloneReader r(in, scope, cloneDataPolicy, cb, cbClosure);
return r.read(vp);
}
@ -2211,6 +2216,12 @@ bool JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes,
}
bool JSStructuredCloneReader::readSharedArrayBuffer(MutableHandleValue vp) {
if (!cloneDataPolicy.isSharedArrayBufferAllowed()) {
JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
JSMSG_SC_NOT_CLONABLE, "SharedArrayBuffer");
return false;
}
uint32_t byteLength;
if (!in.readBytes(&byteLength, sizeof(byteLength))) {
return in.reportTruncated();
@ -2257,14 +2268,19 @@ bool JSStructuredCloneReader::readSharedArrayBuffer(MutableHandleValue vp) {
bool JSStructuredCloneReader::readSharedWasmMemory(uint32_t nbytes,
MutableHandleValue vp) {
JSContext* cx = context();
if (nbytes != 0) {
JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SC_BAD_SERIALIZED_DATA,
"invalid shared wasm memory tag");
return false;
}
JSContext* cx = context();
if (!cloneDataPolicy.isSharedArrayBufferAllowed()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_SC_NOT_CLONABLE, "WebAssembly.Memory");
return false;
}
// Read the SharedArrayBuffer object.
RootedValue payload(cx);
@ -3008,6 +3024,7 @@ using namespace js;
JS_PUBLIC_API bool JS_ReadStructuredClone(
JSContext* cx, JSStructuredCloneData& buf, uint32_t version,
JS::StructuredCloneScope scope, MutableHandleValue vp,
JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure) {
AssertHeapIsIdle();
CHECK_THREAD(cx);
@ -3018,7 +3035,8 @@ JS_PUBLIC_API bool JS_ReadStructuredClone(
return false;
}
const JSStructuredCloneCallbacks* callbacks = optionalCallbacks;
return ReadStructuredClone(cx, buf, scope, vp, callbacks, closure);
return ReadStructuredClone(cx, buf, scope, vp, cloneDataPolicy, callbacks,
closure);
}
JS_PUBLIC_API bool JS_WriteStructuredClone(
@ -3082,7 +3100,7 @@ JS_PUBLIC_API bool JS_StructuredClone(
}
}
return buf.read(cx, vp, callbacks, closure);
return buf.read(cx, vp, JS::CloneDataPolicy(), callbacks, closure);
}
JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(
@ -3139,11 +3157,11 @@ void JSAutoStructuredCloneBuffer::steal(
}
bool JSAutoStructuredCloneBuffer::read(
JSContext* cx, MutableHandleValue vp,
JSContext* cx, MutableHandleValue vp, JS::CloneDataPolicy cloneDataPolicy,
const JSStructuredCloneCallbacks* optionalCallbacks, void* closure) {
MOZ_ASSERT(cx);
return !!JS_ReadStructuredClone(cx, data_, version_, scope_, vp,
optionalCallbacks, closure);
cloneDataPolicy, optionalCallbacks, closure);
}
bool JSAutoStructuredCloneBuffer::write(