[tbb-commits] [Git][tpo/applications/tor-browser][base-browser-115.16.0esr-13.5-1] 7 commits: Bug 1881037 - Part 1: Stop showing unknown protocol error pages for...
ma1 (@ma1)
git at gitlab.torproject.org
Mon Sep 30 22:54:51 UTC 2024
ma1 pushed to branch base-browser-115.16.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
9ce14cc7 by Nika Layzell at 2024-10-01T00:53:35+02:00
Bug 1881037 - Part 1: Stop showing unknown protocol error pages for web-triggered loads, r=smaug,necko-reviewers,kershaw, a=dsmith
Differential Revision: https://phabricator.services.mozilla.com/D217495
- - - - -
63cf9662 by Paul Zuehlcke at 2024-10-01T00:53:37+02:00
Bug 1916659, a=diannaS
Original Revision: https://phabricator.services.mozilla.com/D222629
Differential Revision: https://phabricator.services.mozilla.com/D222934
- - - - -
32373e41 by André Bargull at 2024-10-01T00:53:38+02:00
Bug 1915249: Add more nodiscard. a=RyanVM
Original Revision: https://phabricator.services.mozilla.com/D220311
Differential Revision: https://phabricator.services.mozilla.com/D221663
- - - - -
e6dfa497 by Emilio Cobos Álvarez at 2024-10-01T00:53:40+02:00
Bug 1914106 - Deal with insertRule edge-case. r=jwatt a=RyanVM
When there's trailing garbage after an @import rule we throw, but we
still trigger the load (that's not great but not trivial to change).
Deal with that case before calling ImportRuleLoaded().
Differential Revision: https://phabricator.services.mozilla.com/D219783
- - - - -
35286ac0 by Steve Fink at 2024-10-01T00:53:42+02:00
Bug 1912471 - Disallow deserializing structured clone buffers with transferables more than once r=iain, a=dsmith
Differential Revision: https://phabricator.services.mozilla.com/D220644
- - - - -
bf0a17a2 by Nika Layzell at 2024-10-01T00:53:43+02:00
Bug 1911745 - Unify BrowsingContext flag coherency checks, r=mccr8
Previously these checks were largely diagnostic tools for finding bugs
in other code as it evolves. This unifies the checks a bit more and
makes them stronger for BrowsingContexts created over IPC, providing a
place for more coherency checks to be added in the future.
Differential Revision: https://phabricator.services.mozilla.com/D218860
- - - - -
bf6b766b by Kershaw Chang at 2024-10-01T00:53:46+02:00
Bug 1907726 - Make sure WebTransportSessionProxy::NotifyDatagramReceived is called after OnStopRequest, a=RyanVM
The crash occurs because WebTransportSessionProxy::OnDatagramReceivedInternal is called before WebTransportSessionProxy::OnStopRequest.
When this happens, WebTransportSessionProxy::mTarget is the main thread, so a task is dispatched to the main thread. This causes WebTransportSessionProxy::NotifyDatagramReceived to be called on the main thread.
If WebTransportSessionProxy::NotifyDatagramReceived is invoked while WebTransportSessionProxy::mStopRequestCalled is true, it can lead to OnDatagramReceived being called on the main thread (instead of the socket thread), resulting in a crash.
Original Revision: https://phabricator.services.mozilla.com/D220013
Differential Revision: https://phabricator.services.mozilla.com/D221661
- - - - -
22 changed files:
- browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
- browser/components/prompts/PromptCollection.sys.mjs
- docshell/base/BrowsingContext.cpp
- docshell/base/BrowsingContext.h
- docshell/base/nsDocShell.cpp
- docshell/base/nsDocShell.h
- dom/base/Document.cpp
- dom/base/Document.h
- dom/base/ShadowRoot.cpp
- dom/base/ShadowRoot.h
- dom/filesystem/tests/script_promptHandler.js
- js/public/StructuredClone.h
- js/public/friend/ErrorNumbers.msg
- js/src/jit-test/tests/structured-clone/transferable-cleanup.js
- js/src/jit/IonAnalysis.cpp
- js/src/vm/StructuredClone.cpp
- layout/style/ServoStyleSet.cpp
- layout/style/ServoStyleSet.h
- layout/style/StyleSheet.cpp
- netwerk/ipc/DocumentLoadListener.cpp
- netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
- + testing/web-platform/tests/css/cssom/insertRule-import-trailing-garbage-crash.html
Changes:
=====================================
browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
=====================================
@@ -101,8 +101,29 @@ async function testUploadPrompt(confirmUpload) {
// Wait for confirmation prompt
let prompt = await promptPromise;
ok(prompt, "Shown upload confirmation prompt");
+
is(prompt.ui.button0.label, "Upload", "Accept button label");
+ ok(
+ prompt.ui.button0.disabled,
+ "Accept button should be disabled by the security delay initially."
+ );
+
ok(prompt.ui.button1.hasAttribute("default"), "Cancel is default button");
+ ok(
+ !prompt.ui.button1.disabled,
+ "Cancel button should not be disabled by the security delay."
+ );
+
+ info("Wait for the security delay to pass.");
+ let delayTime = Services.prefs.getIntPref("security.dialog_enable_delay");
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ await new Promise(resolve => setTimeout(resolve, delayTime + 100));
+
+ ok(
+ !prompt.ui.button0.disabled,
+ "Accept button should no longer be disabled."
+ );
+ ok(!prompt.ui.button1.disabled, "Cancel button should remain enabled.");
// Close confirmation prompt
await PromptTestUtils.handlePrompt(prompt, {
=====================================
browser/components/prompts/PromptCollection.sys.mjs
=====================================
@@ -156,7 +156,7 @@ export class PromptCollection {
Services.prompt.MODAL_TYPE_TAB,
title,
message,
- buttonFlags,
+ buttonFlags | Ci.nsIPrompt.BUTTON_DELAY_ENABLE,
acceptLabel,
null,
null,
=====================================
docshell/base/BrowsingContext.cpp
=====================================
@@ -572,9 +572,19 @@ mozilla::ipc::IPCResult BrowsingContext::CreateFromIPC(
context->mRequestContextId = aInit.mRequestContextId;
// NOTE: Private browsing ID is set by `SetOriginAttributes`.
+ if (const char* failure =
+ context->BrowsingContextCoherencyChecks(aOriginProcess)) {
+ mozilla::ipc::IProtocol* actor = aOriginProcess;
+ if (!actor) {
+ actor = ContentChild::GetSingleton();
+ }
+ return IPC_FAIL(actor, "Incoherent BrowsingContext");
+ }
+
Register(context);
- return context->Attach(/* aFromIPC */ true, aOriginProcess);
+ context->Attach(/* aFromIPC */ true, aOriginProcess);
+ return IPC_OK();
}
BrowsingContext::BrowsingContext(WindowContext* aParentWindow,
@@ -786,8 +796,64 @@ void BrowsingContext::Embed() {
}
}
-mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC,
- ContentParent* aOriginProcess) {
+const char* BrowsingContext::BrowsingContextCoherencyChecks(
+ ContentParent* aOriginProcess) {
+#define COHERENCY_ASSERT(condition) \
+ if (!(condition)) return "Assertion " #condition " failed";
+
+ if (mGroup->IsPotentiallyCrossOriginIsolated() !=
+ (Top()->GetOpenerPolicy() ==
+ nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP)) {
+ return "Invalid CrossOriginIsolated state";
+ }
+
+ if (aOriginProcess && !IsContent()) {
+ return "Content cannot create chrome BCs";
+ }
+
+ // LoadContext should generally match our opener or parent.
+ if (IsContent()) {
+ if (RefPtr<BrowsingContext> opener = GetOpener()) {
+ COHERENCY_ASSERT(opener->mType == mType);
+ COHERENCY_ASSERT(opener->mGroup == mGroup);
+ COHERENCY_ASSERT(opener->mUseRemoteTabs == mUseRemoteTabs);
+ COHERENCY_ASSERT(opener->mUseRemoteSubframes == mUseRemoteSubframes);
+ COHERENCY_ASSERT(opener->mPrivateBrowsingId == mPrivateBrowsingId);
+ COHERENCY_ASSERT(
+ opener->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
+ }
+ }
+ if (RefPtr<BrowsingContext> parent = GetParent()) {
+ COHERENCY_ASSERT(parent->mType == mType);
+ COHERENCY_ASSERT(parent->mGroup == mGroup);
+ COHERENCY_ASSERT(parent->mUseRemoteTabs == mUseRemoteTabs);
+ COHERENCY_ASSERT(parent->mUseRemoteSubframes == mUseRemoteSubframes);
+ COHERENCY_ASSERT(parent->mPrivateBrowsingId == mPrivateBrowsingId);
+ COHERENCY_ASSERT(
+ parent->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
+ }
+
+ // UseRemoteSubframes and UseRemoteTabs must match.
+ if (mUseRemoteSubframes && !mUseRemoteTabs) {
+ return "Cannot set useRemoteSubframes without also setting useRemoteTabs";
+ }
+
+ // Double-check OriginAttributes/Private Browsing
+ // Chrome browsing contexts must not have a private browsing OriginAttribute
+ // Content browsing contexts must maintain the equality:
+ // mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
+ if (IsChrome()) {
+ COHERENCY_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
+ } else {
+ COHERENCY_ASSERT(mOriginAttributes.mPrivateBrowsingId ==
+ mPrivateBrowsingId);
+ }
+#undef COHERENCY_ASSERT
+
+ return nullptr;
+}
+
+void BrowsingContext::Attach(bool aFromIPC, ContentParent* aOriginProcess) {
MOZ_DIAGNOSTIC_ASSERT(!mEverAttached);
MOZ_DIAGNOSTIC_ASSERT_IF(aFromIPC, aOriginProcess || XRE_IsContentProcess());
mEverAttached = true;
@@ -806,25 +872,15 @@ mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC,
MOZ_DIAGNOSTIC_ASSERT(mGroup);
MOZ_DIAGNOSTIC_ASSERT(!mIsDiscarded);
- if (mGroup->IsPotentiallyCrossOriginIsolated() !=
- (Top()->GetOpenerPolicy() ==
- nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP)) {
- MOZ_DIAGNOSTIC_ASSERT(aFromIPC);
- if (aFromIPC) {
- auto* actor = aOriginProcess
- ? static_cast<mozilla::ipc::IProtocol*>(aOriginProcess)
- : static_cast<mozilla::ipc::IProtocol*>(
- ContentChild::GetSingleton());
- return IPC_FAIL(
- actor,
- "Invalid CrossOriginIsolated state in BrowsingContext::Attach call");
- } else {
- MOZ_CRASH(
- "Invalid CrossOriginIsolated state in BrowsingContext::Attach call");
+#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
+ // We'll already have checked this if `aFromIPC` is set before calling this
+ // function.
+ if (!aFromIPC) {
+ if (const char* failure = BrowsingContextCoherencyChecks(aOriginProcess)) {
+ MOZ_CRASH_UNSAFE_PRINTF("Incoherent BrowsingContext: %s", failure);
}
}
-
- AssertCoherentLoadContext();
+#endif
// Add ourselves either to our parent or BrowsingContextGroup's child list.
// Important: We shouldn't return IPC_FAIL after this point, since the
@@ -906,7 +962,6 @@ mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC,
if (XRE_IsParentProcess()) {
Canonical()->CanonicalAttach();
}
- return IPC_OK();
}
void BrowsingContext::Detach(bool aFromIPC) {
@@ -1743,40 +1798,6 @@ nsresult BrowsingContext::SetOriginAttributes(const OriginAttributes& aAttrs) {
return NS_OK;
}
-void BrowsingContext::AssertCoherentLoadContext() {
-#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
- // LoadContext should generally match our opener or parent.
- if (IsContent()) {
- if (RefPtr<BrowsingContext> opener = GetOpener()) {
- MOZ_DIAGNOSTIC_ASSERT(opener->mType == mType);
- MOZ_DIAGNOSTIC_ASSERT(opener->mGroup == mGroup);
- MOZ_DIAGNOSTIC_ASSERT(opener->mUseRemoteTabs == mUseRemoteTabs);
- MOZ_DIAGNOSTIC_ASSERT(opener->mUseRemoteSubframes == mUseRemoteSubframes);
- MOZ_DIAGNOSTIC_ASSERT(opener->mPrivateBrowsingId == mPrivateBrowsingId);
- MOZ_DIAGNOSTIC_ASSERT(
- opener->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
- }
- }
- if (RefPtr<BrowsingContext> parent = GetParent()) {
- MOZ_DIAGNOSTIC_ASSERT(parent->mType == mType);
- MOZ_DIAGNOSTIC_ASSERT(parent->mGroup == mGroup);
- MOZ_DIAGNOSTIC_ASSERT(parent->mUseRemoteTabs == mUseRemoteTabs);
- MOZ_DIAGNOSTIC_ASSERT(parent->mUseRemoteSubframes == mUseRemoteSubframes);
- MOZ_DIAGNOSTIC_ASSERT(parent->mPrivateBrowsingId == mPrivateBrowsingId);
- MOZ_DIAGNOSTIC_ASSERT(
- parent->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
- }
-
- // UseRemoteSubframes and UseRemoteTabs must match.
- MOZ_DIAGNOSTIC_ASSERT(
- !mUseRemoteSubframes || mUseRemoteTabs,
- "Cannot set useRemoteSubframes without also setting useRemoteTabs");
-
- // Double-check OriginAttributes/Private Browsing
- AssertOriginAttributesMatchPrivateBrowsing();
-#endif
-}
-
void BrowsingContext::AssertOriginAttributesMatchPrivateBrowsing() {
// Chrome browsing contexts must not have a private browsing OriginAttribute
// Content browsing contexts must maintain the equality:
=====================================
docshell/base/BrowsingContext.h
=====================================
@@ -971,7 +971,18 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool aHasPostData);
private:
- mozilla::ipc::IPCResult Attach(bool aFromIPC, ContentParent* aOriginProcess);
+ // Assert that this BrowsingContext is coherent relative to related
+ // BrowsingContexts. This will be run before the BrowsingContext is attached.
+ //
+ // A non-null string return value indicates that there was a coherency check
+ // failure, which will be handled with either a crash or IPC failure.
+ //
+ // If provided, `aOriginProcess` is the process which is responsible for the
+ // creation of this BrowsingContext.
+ [[nodiscard]] const char* BrowsingContextCoherencyChecks(
+ ContentParent* aOriginProcess);
+
+ void Attach(bool aFromIPC, ContentParent* aOriginProcess);
// Recomputes whether we can execute scripts in this BrowsingContext based on
// the value of AllowJavascript() and whether scripts are allowed in the
@@ -985,10 +996,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void AssertOriginAttributesMatchPrivateBrowsing();
- // Assert that the BrowsingContext's LoadContext flags appear coherent
- // relative to related BrowsingContexts.
- void AssertCoherentLoadContext();
-
friend class ::nsOuterWindowProxy;
friend class ::nsGlobalWindowOuter;
friend class WindowContext;
=====================================
docshell/base/nsDocShell.cpp
=====================================
@@ -6254,7 +6254,7 @@ already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
nsresult nsDocShell::FilterStatusForErrorPage(
nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
- bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
+ bool aIsTopFrame, bool aUseErrorPages,
bool* aSkippedUnknownProtocolNavigation) {
// Errors to be shown only on top-level frames
if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
@@ -6298,18 +6298,10 @@ nsresult nsDocShell::FilterStatusForErrorPage(
if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
// For unknown protocols we only display an error if the load is triggered
- // by the browser itself, or we're replacing the initial document (and
- // nothing else). Showing the error for page-triggered navigations causes
- // annoying behavior for users, see bug 1528305.
- //
- // We could, maybe, try to detect if this is in response to some user
- // interaction (like clicking a link, or something else) and maybe show
- // the error page in that case. But this allows for ctrl+clicking and such
- // to see the error page.
+ // by the browser itself. Showing the error for page-triggered navigations
+ // causes annoying behavior for users, see bug 1528305.
nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
- if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
- StaticPrefs::dom_no_unknown_protocol_error_enabled() &&
- !aIsInitialDocument) {
+ if (!info->TriggeringPrincipal()->IsSystemPrincipal()) {
if (aSkippedUnknownProtocolNavigation) {
*aSkippedUnknownProtocolNavigation = true;
}
@@ -6459,12 +6451,9 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
aStatus == NS_ERROR_CONTENT_BLOCKED);
UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
- bool isInitialDocument =
- !GetExtantDocument() || GetExtantDocument()->IsInitialDocument();
bool skippedUnknownProtocolNavigation = false;
aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
mBrowsingContext->GetUseErrorPages(),
- isInitialDocument,
&skippedUnknownProtocolNavigation);
hadErrorStatus = true;
if (NS_FAILED(aStatus)) {
=====================================
docshell/base/nsDocShell.h
=====================================
@@ -464,7 +464,7 @@ class nsDocShell final : public nsDocLoader,
// navigation.
static nsresult FilterStatusForErrorPage(
nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
- bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
+ bool aIsTopFrame, bool aUseErrorPages,
bool* aSkippedUnknownProtocolNavigation = nullptr);
// Notify consumers of a search being loaded through the observer service:
=====================================
dom/base/Document.cpp
=====================================
@@ -8266,7 +8266,7 @@ void Document::RuleAdded(StyleSheet& aSheet, css::Rule& aRule) {
}
}
-void Document::ImportRuleLoaded(dom::CSSImportRule& aRule, StyleSheet& aSheet) {
+void Document::ImportRuleLoaded(StyleSheet& aSheet) {
if (aSheet.IsApplicable()) {
ApplicableStylesChanged();
}
=====================================
dom/base/Document.h
=====================================
@@ -2135,7 +2135,7 @@ class Document : public nsINode,
void RuleAdded(StyleSheet&, css::Rule&);
void RuleRemoved(StyleSheet&, css::Rule&);
void SheetCloned(StyleSheet&) {}
- void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
+ void ImportRuleLoaded(StyleSheet&);
/**
* Flush notifications for this document and its parent documents
=====================================
dom/base/ShadowRoot.cpp
=====================================
@@ -412,7 +412,7 @@ void ShadowRoot::RuleChanged(StyleSheet& aSheet, css::Rule*,
ApplicableRulesChanged();
}
-void ShadowRoot::ImportRuleLoaded(CSSImportRule&, StyleSheet& aSheet) {
+void ShadowRoot::ImportRuleLoaded(StyleSheet& aSheet) {
if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aSheet);
}
=====================================
dom/base/ShadowRoot.h
=====================================
@@ -86,7 +86,7 @@ class ShadowRoot final : public DocumentFragment,
void RuleAdded(StyleSheet&, css::Rule&);
void RuleRemoved(StyleSheet&, css::Rule&);
void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
- void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
+ void ImportRuleLoaded(StyleSheet&);
void SheetCloned(StyleSheet&);
void StyleSheetApplicableStateChanged(StyleSheet&);
=====================================
dom/filesystem/tests/script_promptHandler.js
=====================================
@@ -2,7 +2,45 @@
let dialogObserverTopic = "common-dialog-loaded";
-function dialogObserver(subj, topic, data) {
+function waitForButtonEnabledState(button) {
+ return new Promise(resolve => {
+ // Check if the button is already enabled (not disabled)
+ if (!button.disabled) {
+ resolve();
+ return;
+ }
+
+ // Create a MutationObserver instance
+ let win = button.ownerGlobal;
+ let { MutationObserver } = win;
+ const observer = new MutationObserver(mutationsList => {
+ for (const mutation of mutationsList) {
+ if (
+ mutation.type === "attributes" &&
+ mutation.attributeName === "disabled"
+ ) {
+ if (!button.disabled) {
+ // Resolve the promise when the button is enabled
+ observer.disconnect(); // Stop observing
+ resolve();
+ }
+ }
+ }
+ });
+
+ // Start observing the button for changes to the 'disabled' attribute
+ observer.observe(button, {
+ attributes: true,
+ attributeFilter: ["disabled"],
+ });
+ });
+}
+
+async function dialogObserver(subj) {
+ let dialog = subj.document.querySelector("dialog");
+ let acceptButton = dialog.getButton("accept");
+ await waitForButtonEnabledState(acceptButton);
+
subj.document.querySelector("dialog").acceptDialog();
sendAsyncMessage("promptAccepted");
}
=====================================
js/public/StructuredClone.h
=====================================
@@ -744,6 +744,7 @@ class JS_PUBLIC_API JSAutoStructuredCloneBuffer {
#define JS_SCERR_WASM_NO_TRANSFER 6
#define JS_SCERR_NOT_CLONABLE 7
#define JS_SCERR_NOT_CLONABLE_WITH_COOP_COEP 8
+#define JS_SCERR_TRANSFERABLE_TWICE 9
JS_PUBLIC_API bool JS_ReadUint32Pair(JSStructuredCloneReader* r, uint32_t* p1,
uint32_t* p2);
=====================================
js/public/friend/ErrorNumbers.msg
=====================================
@@ -527,6 +527,7 @@ MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clo
MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})")
MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
+MSG_DEF(JSMSG_SC_TRANSFERABLE_TWICE, 0, JSEXN_TYPEERR, "structured clone cannot transfer twice")
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data")
MSG_DEF(JSMSG_SC_NOT_CLONABLE, 1, JSEXN_TYPEERR, "The {0} object cannot be serialized. The Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP headers will enable this in the future.")
MSG_DEF(JSMSG_SC_NOT_CLONABLE_WITH_COOP_COEP, 1, JSEXN_TYPEERR, "The {0} object cannot be serialized. The Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP headers can be used to enable this.")
=====================================
js/src/jit-test/tests/structured-clone/transferable-cleanup.js
=====================================
@@ -160,6 +160,15 @@ function testMultiWithDeserializeReadTransferErrorHelper(g, BASE, desc) {
} catch (e) {
assertEq(e.message.includes("invalid transferable"), true);
}
+
+ try {
+ // This fails without logging anything, since the re-transfer will be caught
+ // by looking at its header before calling any callbacks.
+ let clone = deserialize(s);
+ } catch (e) {
+ assertEq(e.message.includes("cannot transfer twice"), true);
+ }
+
s = null;
gc();
printTrace(arguments.callee.name, g, BASE, obj.log, "deserialize");
@@ -170,6 +179,7 @@ function testMultiWithDeserializeReadTransferErrorHelper(g, BASE, desc) {
// which comes before the main reading. obj transfer data is now owned by its
// clone. obj3 transfer data was not successfully handed over to a new object,
// so it is still owned by the clone buffer and must be discarded with freeTransfer.
+ // 'F' means the data is freed.
BASE + 3, "F",
], "deserialize " + desc);
obj.log = null;
=====================================
js/src/jit/IonAnalysis.cpp
=====================================
@@ -29,8 +29,9 @@ using MPhiUseIteratorStack =
// Look for Phi uses with a depth-first search. If any uses are found the stack
// of MPhi instructions is returned in the |worklist| argument.
-static bool DepthFirstSearchUse(MIRGenerator* mir,
- MPhiUseIteratorStack& worklist, MPhi* phi) {
+[[nodiscard]] static bool DepthFirstSearchUse(MIRGenerator* mir,
+ MPhiUseIteratorStack& worklist,
+ MPhi* phi) {
// Push a Phi and the next use to iterate over in the worklist.
auto push = [&worklist](MPhi* phi, MUseIterator use) -> bool {
phi->setInWorklist();
@@ -131,9 +132,9 @@ static bool DepthFirstSearchUse(MIRGenerator* mir,
return true;
}
-static bool FlagPhiInputsAsImplicitlyUsed(MIRGenerator* mir, MBasicBlock* block,
- MBasicBlock* succ,
- MPhiUseIteratorStack& worklist) {
+[[nodiscard]] static bool FlagPhiInputsAsImplicitlyUsed(
+ MIRGenerator* mir, MBasicBlock* block, MBasicBlock* succ,
+ MPhiUseIteratorStack& worklist) {
// When removing an edge between 2 blocks, we might remove the ability of
// later phases to figure out that the uses of a Phi should be considered as
// a use of all its inputs. Thus we need to mark the Phi inputs as being
@@ -265,7 +266,7 @@ static MInstructionIterator FindFirstInstructionAfterBail(MBasicBlock* block) {
// Given an iterator pointing to the first removed instruction, mark
// the operands of each removed instruction as having implicit uses.
-static bool FlagOperandsAsImplicitlyUsedAfter(
+[[nodiscard]] static bool FlagOperandsAsImplicitlyUsedAfter(
MIRGenerator* mir, MBasicBlock* block, MInstructionIterator firstRemoved) {
MOZ_ASSERT(firstRemoved->block() == block);
@@ -312,8 +313,8 @@ static bool FlagOperandsAsImplicitlyUsedAfter(
return true;
}
-static bool FlagEntryResumePointOperands(MIRGenerator* mir,
- MBasicBlock* block) {
+[[nodiscard]] static bool FlagEntryResumePointOperands(MIRGenerator* mir,
+ MBasicBlock* block) {
// Flag observable operands of the entry resume point as having implicit uses.
MResumePoint* rp = block->entryResumePoint();
while (rp) {
@@ -334,8 +335,8 @@ static bool FlagEntryResumePointOperands(MIRGenerator* mir,
return true;
}
-static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
- MBasicBlock* block) {
+[[nodiscard]] static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
+ MBasicBlock* block) {
return FlagEntryResumePointOperands(mir, block) &&
FlagOperandsAsImplicitlyUsedAfter(mir, block, block->begin());
}
@@ -420,12 +421,16 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) {
if (!block->isMarked()) {
// If we are removing the block entirely, mark the operands of every
// instruction as being implicitly used.
- FlagAllOperandsAsImplicitlyUsed(mir, block);
+ if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
+ return false;
+ }
} else if (block->alwaysBails()) {
// If we are only trimming instructions after a bail, only mark operands
// of removed instructions.
MInstructionIterator firstRemoved = FindFirstInstructionAfterBail(block);
- FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved);
+ if (!FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved)) {
+ return false;
+ }
}
}
@@ -503,7 +508,8 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) {
return true;
}
-static bool SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block) {
+[[nodiscard]] static bool SplitCriticalEdgesForBlock(MIRGraph& graph,
+ MBasicBlock* block) {
if (block->numSuccessors() < 2) {
return true;
}
@@ -767,8 +773,8 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) {
return true;
}
-static bool MaybeFoldDiamondConditionBlock(MIRGraph& graph,
- MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldDiamondConditionBlock(
+ MIRGraph& graph, MBasicBlock* initialBlock) {
MOZ_ASSERT(IsDiamondPattern(initialBlock));
// Optimize the MIR graph to improve the code generated for conditional
@@ -936,8 +942,8 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) {
return false;
}
-static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph,
- MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldTriangleConditionBlock(
+ MIRGraph& graph, MBasicBlock* initialBlock) {
MOZ_ASSERT(IsTrianglePattern(initialBlock));
// Optimize the MIR graph to improve the code generated for boolean
@@ -1089,8 +1095,8 @@ static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph,
return true;
}
-static bool MaybeFoldConditionBlock(MIRGraph& graph,
- MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldConditionBlock(MIRGraph& graph,
+ MBasicBlock* initialBlock) {
if (IsDiamondPattern(initialBlock)) {
return MaybeFoldDiamondConditionBlock(graph, initialBlock);
}
@@ -1100,7 +1106,8 @@ static bool MaybeFoldConditionBlock(MIRGraph& graph,
return true;
}
-static bool MaybeFoldTestBlock(MIRGraph& graph, MBasicBlock* initialBlock) {
+[[nodiscard]] static bool MaybeFoldTestBlock(MIRGraph& graph,
+ MBasicBlock* initialBlock) {
// Handle test expressions on more than two inputs. For example
// |if ((x > 10) && (y > 20) && (z > 30)) { ... }|, which results in the below
// pattern.
@@ -2752,7 +2759,9 @@ bool jit::RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph,
continue;
}
- FlagAllOperandsAsImplicitlyUsed(mir, block);
+ if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
+ return false;
+ }
}
// Find unmarked blocks and remove them.
@@ -4003,8 +4012,8 @@ bool jit::EliminateRedundantShapeGuards(MIRGraph& graph) {
return true;
}
-static bool TryEliminateGCBarriersForAllocation(TempAllocator& alloc,
- MInstruction* allocation) {
+[[nodiscard]] static bool TryEliminateGCBarriersForAllocation(
+ TempAllocator& alloc, MInstruction* allocation) {
MOZ_ASSERT(allocation->type() == MIRType::Object);
JitSpew(JitSpew_RedundantGCBarriers, "Analyzing allocation %s",
=====================================
js/src/vm/StructuredClone.cpp
=====================================
@@ -172,17 +172,25 @@ enum StructuredDataType : uint32_t {
/*
* Format of transfer map:
- * <SCTAG_TRANSFER_MAP_HEADER, TransferableMapHeader(UNREAD|TRANSFERRED)>
- * numTransferables (64 bits)
- * array of:
- * <SCTAG_TRANSFER_MAP_*, TransferableOwnership>
- * pointer (64 bits)
- * extraData (64 bits), eg byte length for ArrayBuffers
+ * - <SCTAG_TRANSFER_MAP_HEADER, UNREAD|TRANSFERRING|TRANSFERRED>
+ * - numTransferables (64 bits)
+ * - array of:
+ * - <SCTAG_TRANSFER_MAP_*, TransferableOwnership> pointer (64
+ * bits)
+ * - extraData (64 bits), eg byte length for ArrayBuffers
+ * - any data written for custom transferables
*/
// Data associated with an SCTAG_TRANSFER_MAP_HEADER that tells whether the
-// contents have been read out yet or not.
-enum TransferableMapHeader { SCTAG_TM_UNREAD = 0, SCTAG_TM_TRANSFERRED };
+// contents have been read out yet or not. TRANSFERRING is for the case where we
+// have started but not completed reading, which due to errors could mean that
+// there are things still owned by the clone buffer that need to be released, so
+// discarding should not just be skipped.
+enum TransferableMapHeader {
+ SCTAG_TM_UNREAD = 0,
+ SCTAG_TM_TRANSFERRING,
+ SCTAG_TM_TRANSFERRED
+};
static inline uint64_t PairToUInt64(uint32_t tag, uint32_t data) {
return uint64_t(data) | (uint64_t(tag) << 32);
@@ -693,6 +701,10 @@ static void ReportDataCloneError(JSContext* cx,
errorNumber = JSMSG_SC_SHMEM_TRANSFERABLE;
break;
+ case JS_SCERR_TRANSFERABLE_TWICE:
+ errorNumber = JSMSG_SC_TRANSFERABLE_TWICE;
+ break;
+
case JS_SCERR_TYPED_ARRAY_DETACHED:
errorNumber = JSMSG_TYPED_ARRAY_DETACHED;
break;
@@ -3209,11 +3221,21 @@ bool JSStructuredCloneReader::readTransferMap() {
return in.reportTruncated();
}
+ auto transferState = static_cast<TransferableMapHeader>(data);
+
if (tag != SCTAG_TRANSFER_MAP_HEADER ||
- TransferableMapHeader(data) == SCTAG_TM_TRANSFERRED) {
+ transferState == SCTAG_TM_TRANSFERRED) {
return true;
}
+ if (transferState == SCTAG_TM_TRANSFERRING) {
+ ReportDataCloneError(cx, callbacks, JS_SCERR_TRANSFERABLE_TWICE, closure);
+ return false;
+ }
+
+ headerPos.write(
+ PairToUInt64(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_TRANSFERRING));
+
uint64_t numTransferables;
MOZ_ALWAYS_TRUE(in.readPair(&tag, &data));
if (!in.read(&numTransferables)) {
@@ -3329,7 +3351,7 @@ bool JSStructuredCloneReader::readTransferMap() {
#ifdef DEBUG
SCInput::getPair(headerPos.peek(), &tag, &data);
MOZ_ASSERT(tag == SCTAG_TRANSFER_MAP_HEADER);
- MOZ_ASSERT(TransferableMapHeader(data) != SCTAG_TM_TRANSFERRED);
+ MOZ_ASSERT(TransferableMapHeader(data) == SCTAG_TM_TRANSFERRING);
#endif
headerPos.write(
PairToUInt64(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_TRANSFERRED));
=====================================
layout/style/ServoStyleSet.cpp
=====================================
@@ -954,7 +954,7 @@ static OriginFlags ToOriginFlags(StyleOrigin aOrigin) {
}
}
-void ServoStyleSet::ImportRuleLoaded(dom::CSSImportRule&, StyleSheet& aSheet) {
+void ServoStyleSet::ImportRuleLoaded(StyleSheet& aSheet) {
if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aSheet);
}
=====================================
layout/style/ServoStyleSet.h
=====================================
@@ -133,7 +133,7 @@ class ServoStyleSet {
void RuleRemoved(StyleSheet&, css::Rule&);
void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
void SheetCloned(StyleSheet&);
- void ImportRuleLoaded(dom::CSSImportRule&, StyleSheet&);
+ void ImportRuleLoaded(StyleSheet&);
// Runs style invalidation due to document state changes.
void InvalidateStyleForDocumentStateChanges(
=====================================
layout/style/StyleSheet.cpp
=====================================
@@ -836,15 +836,19 @@ StyleSheet::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
if (!aSheet->GetParentSheet()) {
return NS_OK; // ignore if sheet has been detached already
}
- MOZ_ASSERT(this == aSheet->GetParentSheet(),
- "We are being notified of a sheet load for a sheet that is not "
- "our child!");
+ MOZ_DIAGNOSTIC_ASSERT(this == aSheet->GetParentSheet(),
+ "We are being notified of a sheet load for a sheet "
+ "that is not our child!");
if (NS_FAILED(aStatus)) {
return NS_OK;
}
-
- MOZ_ASSERT(aSheet->GetOwnerRule());
- NOTIFY(ImportRuleLoaded, (*aSheet->GetOwnerRule(), *aSheet));
+ // The assert below should hold if we stop triggering import loads for invalid
+ // insertRule() calls, see bug 1914106.
+ // MOZ_ASSERT(aSheet->GetOwnerRule());
+ if (!aSheet->GetOwnerRule()) {
+ return NS_OK;
+ }
+ NOTIFY(ImportRuleLoaded, (*aSheet));
return NS_OK;
}
=====================================
netwerk/ipc/DocumentLoadListener.cpp
=====================================
@@ -2316,15 +2316,9 @@ bool DocumentLoadListener::DocShellWillDisplayContent(nsresult aStatus) {
auto* loadingContext = GetLoadingBrowsingContext();
- bool isInitialDocument = true;
- if (WindowGlobalParent* currentWindow =
- loadingContext->GetCurrentWindowGlobal()) {
- isInitialDocument = currentWindow->IsInitialDocument();
- }
-
nsresult rv = nsDocShell::FilterStatusForErrorPage(
aStatus, mChannel, mLoadStateLoadType, loadingContext->IsTop(),
- loadingContext->GetUseErrorPages(), isInitialDocument, nullptr);
+ loadingContext->GetUseErrorPages(), nullptr);
if (NS_SUCCEEDED(rv)) {
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
=====================================
netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
=====================================
@@ -1042,15 +1042,6 @@ void WebTransportSessionProxy::NotifyDatagramReceived(
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mTarget->IsOnCurrentThread());
- if (!mStopRequestCalled) {
- CopyableTArray<uint8_t> copied(aData);
- mPendingEvents.AppendElement(
- [self = RefPtr{this}, data = std::move(copied)]() mutable {
- self->NotifyDatagramReceived(std::move(data));
- });
- return;
- }
-
if (mState != WebTransportSessionProxyState::ACTIVE || !mListener) {
return;
}
@@ -1066,6 +1057,15 @@ NS_IMETHODIMP WebTransportSessionProxy::OnDatagramReceivedInternal(
{
MutexAutoLock lock(mMutex);
+ if (!mStopRequestCalled) {
+ CopyableTArray<uint8_t> copied(aData);
+ mPendingEvents.AppendElement(
+ [self = RefPtr{this}, data = std::move(copied)]() mutable {
+ self->OnDatagramReceivedInternal(std::move(data));
+ });
+ return NS_OK;
+ }
+
if (!mTarget->IsOnCurrentThread()) {
return mTarget->Dispatch(NS_NewRunnableFunction(
"WebTransportSessionProxy::OnDatagramReceived",
=====================================
testing/web-platform/tests/css/cssom/insertRule-import-trailing-garbage-crash.html
=====================================
@@ -0,0 +1,6 @@
+<!doctype html>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1914106">
+<style></style>
+<script>
+document.querySelector("style").sheet.insertRule("@import url('data:text/css,:root{background:red}');html,body{/* random garbage */}");
+</script>
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/b97760ca63ebd1c292878c079a524c330a1826d6...bf6b766b0f43e8e911f97628719c810aa2c89e42
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/b97760ca63ebd1c292878c079a524c330a1826d6...bf6b766b0f43e8e911f97628719c810aa2c89e42
You're receiving this email because of your account on gitlab.torproject.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20240930/041d2123/attachment-0001.htm>
More information about the tbb-commits
mailing list