JSObject* ReadStructuredCloneImageData(JSContext* aCx, JSStructuredCloneReader* aReader) { // Read the information out of the stream. uint32_t width, height; JS::Rooted<JS::Value> dataArray(aCx); if (!JS_ReadUint32Pair(aReader, &width, &height) || !JS_ReadTypedArray(aReader, &dataArray)) { return nullptr; } MOZ_ASSERT(dataArray.isObject()); // Protect the result from a moving GC in ~nsRefPtr. JS::Rooted<JSObject*> result(aCx); { // Construct the ImageData. nsRefPtr<ImageData> imageData = new ImageData(width, height, dataArray.toObject()); // Wrap it in a JS::Value. if (!imageData->WrapObject(aCx, nullptr, &result)) { return nullptr; } } return result; }
KeyAlgorithm* AesKeyAlgorithm::Create(nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader) { uint32_t length, zero; nsString name; bool read = JS_ReadUint32Pair(aReader, &length, &zero) && ReadString(aReader, name); if (!read) { return nullptr; } return new AesKeyAlgorithm(aGlobal, name, length); }
bool StructuredCloneBlob::Holder::ReadStructuredCloneInternal( JSContext* aCx, JSStructuredCloneReader* aReader, StructuredCloneHolder* aHolder) { uint32_t length; uint32_t version; if (!JS_ReadUint32Pair(aReader, &length, &version)) { return false; } uint32_t blobOffset; uint32_t blobCount; if (!JS_ReadUint32Pair(aReader, &blobOffset, &blobCount)) { return false; } if (blobCount) { #ifdef FUZZING if (blobOffset >= aHolder->BlobImpls().Length()) { return false; } #endif BlobImpls().AppendElements(&aHolder->BlobImpls()[blobOffset], blobCount); } JSStructuredCloneData data(mStructuredCloneScope); while (length) { size_t size; char* buffer = data.AllocateBytes(length, &size); if (!buffer || !JS_ReadBytes(aReader, buffer, size)) { return false; } length -= size; } mBuffer = MakeUnique<JSAutoStructuredCloneBuffer>( mStructuredCloneScope, &StructuredCloneHolder::sCallbacks, this); mBuffer->adopt(std::move(data), version, &StructuredCloneHolder::sCallbacks); return true; }
bool RTCCertificate::ReadStructuredClone(JSStructuredCloneReader* aReader) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return false; } uint32_t version, authType; if (!JS_ReadUint32Pair(aReader, &version, &authType) || version != RTCCERTIFICATE_SC_VERSION) { return false; } mAuthType = static_cast<SSLKEAType>(authType); uint32_t high, low; if (!JS_ReadUint32Pair(aReader, &high, &low)) { return false; } mExpires = static_cast<PRTime>(high) << 32 | low; return ReadPrivateKey(aReader, locker) && ReadCertificate(aReader, locker); }
bool CryptoKey::ReadStructuredClone(JSStructuredCloneReader* aReader) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return false; } // Ensure that NSS is initialized. if (!EnsureNSSInitializedChromeOrContent()) { return false; } uint32_t version; CryptoBuffer sym, priv, pub; bool read = JS_ReadUint32Pair(aReader, &mAttributes, &version) && (version == CRYPTOKEY_SC_VERSION) && ReadBuffer(aReader, sym) && ReadBuffer(aReader, priv) && ReadBuffer(aReader, pub) && mAlgorithm.ReadStructuredClone(aReader); if (!read) { return false; } if (sym.Length() > 0 && !mSymKey.Assign(sym)) { return false; } if (priv.Length() > 0) { mPrivateKey = CryptoKey::PrivateKeyFromPkcs8(priv, locker); } if (pub.Length() > 0) { mPublicKey = CryptoKey::PublicKeyFromSpki(pub, locker); } // Ensure that what we've read is consistent // If the attributes indicate a key type, should have a key of that type if (!((GetKeyType() == SECRET && mSymKey.Length() > 0) || (GetKeyType() == PRIVATE && mPrivateKey) || (GetKeyType() == PUBLIC && mPublicKey))) { return false; } return true; }
bool CryptoKey::ReadStructuredClone(JSStructuredCloneReader* aReader) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) { return false; } uint32_t zero; CryptoBuffer sym, priv, pub; nsRefPtr<KeyAlgorithm> algorithm; bool read = JS_ReadUint32Pair(aReader, &mAttributes, &zero) && ReadBuffer(aReader, sym) && ReadBuffer(aReader, priv) && ReadBuffer(aReader, pub) && (algorithm = KeyAlgorithm::Create(mGlobal, aReader)); if (!read) { return false; } if (sym.Length() > 0) { mSymKey = sym; } if (priv.Length() > 0) { mPrivateKey = CryptoKey::PrivateKeyFromPkcs8(priv, locker); } if (pub.Length() > 0) { mPublicKey = CryptoKey::PublicKeyFromSpki(pub, locker); } mAlgorithm = algorithm; // Ensure that what we've read is consistent // If the attributes indicate a key type, should have a key of that type if (!((GetKeyType() == SECRET && mSymKey.Length() > 0) || (GetKeyType() == PRIVATE && mPrivateKey) || (GetKeyType() == PUBLIC && mPublicKey))) { return false; } return true; }
bool URLParams::ReadStructuredClone(JSStructuredCloneReader* aReader) { MOZ_ASSERT(aReader); DeleteAll(); uint32_t nParams, zero; nsAutoString key, value; if (!JS_ReadUint32Pair(aReader, &nParams, &zero)) { return false; } MOZ_ASSERT(zero == 0); for (uint32_t i = 0; i < nParams; ++i) { if (!ReadString(aReader, key) || !ReadString(aReader, value)) { return false; } Append(key, value); } return true; }
// Helper functions for structured cloning inline bool ReadString(JSStructuredCloneReader* aReader, nsString& aString) { MOZ_ASSERT(aReader); bool read; uint32_t nameLength, zero; read = JS_ReadUint32Pair(aReader, &nameLength, &zero); if (!read) { return false; } MOZ_ASSERT(zero == 0); aString.SetLength(nameLength); size_t charSize = sizeof(nsString::char_type); read = JS_ReadBytes(aReader, (void*) aString.BeginWriting(), nameLength * charSize); if (!read) { return false; } return true; }
JSObject* StructuredCloneHelper::ReadCallback(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, uint32_t aIndex) { MOZ_ASSERT(mSupportsCloning); if (aTag == SCTAG_DOM_BLOB) { MOZ_ASSERT(aIndex < mBlobImplArray.Length()); nsRefPtr<BlobImpl> blobImpl = mBlobImplArray[aIndex]; // nsRefPtr<File> needs to go out of scope before toObjectOrNull() is // called because the static analysis thinks dereferencing XPCOM objects // can GC (because in some cases it can!), and a return statement with a // JSObject* type means that JSObject* is on the stack as a raw pointer // while destructors are running. JS::Rooted<JS::Value> val(aCx); { nsRefPtr<Blob> blob = Blob::Create(mParent, blobImpl); if (!ToJSValue(aCx, blob, &val)) { return nullptr; } } return &val.toObject(); } if (aTag == SCTAG_DOM_FILELIST) { JS::Rooted<JS::Value> val(aCx); { nsRefPtr<FileList> fileList = new FileList(mParent); // |aIndex| is the number of BlobImpls to use from |offset|. uint32_t tag, offset; if (!JS_ReadUint32Pair(aReader, &tag, &offset)) { return nullptr; } MOZ_ASSERT(tag == 0); for (uint32_t i = 0; i < aIndex; ++i) { uint32_t index = offset + i; MOZ_ASSERT(index < mBlobImplArray.Length()); nsRefPtr<BlobImpl> blobImpl = mBlobImplArray[index]; MOZ_ASSERT(blobImpl->IsFile()); nsRefPtr<File> file = File::Create(mParent, blobImpl); if (!fileList->Append(file)) { return nullptr; } } if (!ToJSValue(aCx, fileList, &val)) { return nullptr; } } return &val.toObject(); } if (aTag == SCTAG_DOM_IMAGEBITMAP) { // Get the current global object. // This can be null. nsCOMPtr<nsIGlobalObject> parent = do_QueryInterface(mParent); // aIndex is the index of the cloned image. return ImageBitmap::ReadStructuredClone(aCx, aReader, parent, GetImages(), aIndex); } return NS_DOMReadStructuredClone(aCx, aReader, aTag, aIndex, nullptr); }