Firefox · DOM
CVE-2025-1943
Memory Corruption in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/fetch/FetchParent.cpp |
modified | |
ifdom/fetch/FetchService.cpp |
modified |
Files Changed
dom/credentialmanagement/identity/IdentityCredential.cppdom/fetch/FetchParent.cppdom/fetch/FetchService.cppdom/fetch/FetchService.hdom/serviceworkers/FetchEventOpProxyChild.cppdom/serviceworkers/FetchEventOpProxyChild.htoolkit/components/contentanalysis/ContentAnalysis.cpptoolkit/components/resistfingerprinting/nsUserCharacteristics.cppxpcom/threads/MozPromise.h
Patch
diff --git a/dom/credentialmanagement/identity/IdentityCredential.cpp b/dom/credentialmanagement/identity/IdentityCredential.cpp
index 323b020db68..d06c9078678 100644
--- a/dom/credentialmanagement/identity/IdentityCredential.cpp
+++ b/dom/credentialmanagement/identity/IdentityCredential.cpp
@@ -995,9 +995,7 @@ IdentityCredential::DiscoverFromExternalSourceInMainProcess(
nsresult rv = NS_NewTimerWithCallback(
getter_AddRefs(timeout),
[=](auto) {
- if (!result->IsResolved()) {
- result->Reject(NS_ERROR_DOM_NETWORK_ERR, __func__);
- }
+ result->Reject(NS_ERROR_DOM_NETWORK_ERR, __func__);
IdentityCredential::CloseUserInterface(browsingContext);
},
StaticPrefs::
diff --git a/dom/fetch/FetchParent.cpp b/dom/fetch/FetchParent.cpp
index 8b82381abea..6f969246aab 100644
--- a/dom/fetch/FetchParent.cpp
+++ b/dom/fetch/FetchParent.cpp
@@ -199,8 +199,7 @@ IPCResult FetchParent::RecvFetchOp(FetchOpArgs&& aArgs) {
})));
}
- bool isResolved =
- self->mResponsePromises->GetResponseEndPromise()->IsResolved();
+ bool isResolved = self->mResponsePromises->IsResponseEndPromiseResolved();
if (!isResolved && self->mIsWorkerFetch) {
// track only unresolved promises for worker fetch requests
// this is needed for clean-up of keepalive requests
diff --git a/dom/fetch/FetchService.cpp b/dom/fetch/FetchService.cpp
index b854d1e9882..b5e60bbd27f 100644
--- a/dom/fetch/FetchService.cpp
+++ b/dom/fetch/FetchService.cpp
@@ -68,6 +68,7 @@ FetchServicePromises::GetResponseEndPromise() {
void FetchServicePromises::ResolveResponseAvailablePromise(
FetchServiceResponse&& aResponse, StaticString aMethodName) {
if (mAvailablePromise) {
+ mAvailablePromiseResolved = true;
mAvailablePromise->Resolve(std::move(aResponse), aMethodName);
}
}
@@ -82,6 +83,7 @@ void FetchServicePromises::RejectResponseAvailablePromise(
void FetchServicePromises::ResolveResponseTimingPromise(
ResponseTiming&& aTiming, StaticString aMethodName) {
if (mTimingPromise) {
+ mTimingPromiseResolved = true;
mTimingPromise->Resolve(std::move(aTiming), aMethodName);
}
}
@@ -96,6 +98,7 @@ void FetchServicePromises::RejectResponseTimingPromise(
void FetchServicePromises::ResolveResponseEndPromise(ResponseEndArgs&& aArgs,
StaticString aMethodName) {
if (mEndPromise) {
+ mEndPromiseResolved = true;
mEndPromise->Resolve(std::move(aArgs), aMethodName);
}
}
@@ -345,15 +348,11 @@ void FetchService::FetchInstance::Cancel(bool aForceAbort) {
mArgs.as<WorkerFetchArgs>().mResponseEndPromiseHolder.Disconnect();
- MOZ_ASSERT(
- !mArgs.as<WorkerFetchArgs>().mFetchParentPromise->IsResolved());
- if (!mArgs.as<WorkerFetchArgs>().mFetchParentPromise->IsResolved()) {
- // the parent promise resolution leads to deleting of actors
- // mActorDying prevents further access to FetchParent
- mActorDying = true;
- mArgs.as<WorkerFetchArgs>().mFetchParentPromise->Resolve(true,
- __func__);
- }
+ // the parent promise resolution leads to deleting of actors
+ // mActorDying prevents further access to FetchParent
+ mActorDying = true;
+ mArgs.as<WorkerFetchArgs>().mFetchParentPromise->Resolve(true,
+ __func__);
}
}
return;
@@ -412,24 +411,21 @@ void FetchService::FetchInstance::OnResponseEnd(
if (aReason == eAborted) {
// If ResponseAvailablePromise has not resolved yet, resolved with
- // NS_ERROR_DOM_ABORT_ERR response.
- if (!mPromises->GetResponseAvailablePromise()->IsResolved()) {
- mPromises->ResolveResponseAvailablePromise(
- InternalResponse::NetworkError(NS_ERROR_DOM_ABORT_ERR), __func__);
- }
+ // NS_ERROR_DOM_ABORT_ERR response. If the promise is already resolved,
+ // this will have no effect.
+ mPromises->ResolveResponseAvailablePromise(
+ InternalResponse::NetworkError(NS_ERROR_DOM_ABORT_ERR), __func__);
// If ResponseTimingPromise has not resolved yet, resolved with empty
- // ResponseTiming.
- if (!mPromises->GetResponseTimingPromise()->IsResolved()) {
- mPromises->ResolveResponseTimingPromise(ResponseTiming(), __func__);
- }
+ // ResponseTiming. If the promise is already resolved, this has no effect.
+ mPromises->ResolveResponseTimingPromise(ResponseTiming(), __func__);
// Resolve the ResponseEndPromise
mPromises->ResolveResponseEndPromise(ResponseEndArgs(aReason), __func__);
return;
}
- MOZ_ASSERT(mPromises->GetResponseAvailablePromise()->IsResolved() &&
- mPromises->GetResponseTimingPromise()->IsResolved());
+ MOZ_ASSERT(mPromises->IsResponseAvailablePromiseResolved() &&
+ mPromises->IsResponseTimingPromiseResolved());
// Resolve the ResponseEndPromise
mPromises->ResolveResponseEndPromise(ResponseEndArgs(aReason), __func__);
@@ -542,7 +538,7 @@ void FetchService::FetchInstance::OnReportPerformanceTiming() {
MOZ_ASSERT(mFetchDriver);
MOZ_ASSERT(mPromises);
- if (mPromises->GetResponseTimingPromise()->IsResolved()) {
+ if (mPromises->IsResponseTimingPromiseResolved()) {
return;
}
@@ -872,7 +868,7 @@ RefPtr<FetchServicePromises> FetchService::Fetch(FetchArgs&& aArgs) {
RefPtr<FetchServicePromises> promises = fetch->Fetch();
MOZ_ASSERT(promises);
- if (!promises->GetResponseAvailablePromise()->IsResolved()) {
+ if (!promises->IsResponseAvailablePromiseResolved()) {
// Insert the created FetchInstance into FetchInstanceTable.
if (!mFetchInstanceTable.WithEntryHandle(promises, [&](auto&& entry) {
if (entry.HasEntry()) {
diff --git a/dom/fetch/FetchService.h b/dom/fetch/FetchService.h
index 5af939bea49..e98aaa4d278 100644
--- a/dom/fetch/FetchService.h
+++ b/dom/fetch/FetchService.h
@@ -47,6 +47,12 @@ class FetchServicePromises final {
RefPtr<FetchServiceResponseTimingPromise> GetResponseTimingPromise();
RefPtr<FetchServiceResponseEndPromise> GetResponseEndPromise();
+ bool IsResponseAvailablePromiseResolved() {
+ return mAvailablePromiseResolved;
+ }
+ bool IsResponseTimingPromiseResolved() { return mTimingPromiseResolved; }
+ bool IsResponseEndPromiseResolved() { return mEndPromiseResolved; }
+
void ResolveResponseAvailablePromise(FetchServiceResponse&& aResponse,
StaticString aMethodName);
void RejectResponseAvailablePromise(const CopyableErrorResult&& aError,
@@ -66,6 +72,13 @@ class FetchServicePromises final {
RefPtr<FetchServiceResponseAvailablePromise::Private> mAvailablePromise;
RefPtr<FetchServiceResponseTimingPromise::Private> mTimingPromise;
RefPtr<FetchServiceResponseEndPromise::Private> mEndPromise;
+
+ // The MozPromise interface intentionally does not expose synchronous access
+ // to the internal resolved/rejected state. Instead, we track whether or not
+ // we've called Resolve on the FetchServicePromises.
+ bool mAvailablePromiseResolved = false;
+ bool mTimingPromiseResolved = false;
+ bool mEndPromiseResolved = false;
};
/**
diff --git a/dom/serviceworkers/FetchEventOpProxyChild.cpp b/dom/serviceworkers/FetchEventOpProxyChild.cpp
index 8e437356ec5..3fd531373c0 100644
--- a/dom/serviceworkers/FetchEventOpProxyChild.cpp
+++ b/dom/serviceworkers/FetchEventOpProxyChild.cpp
@@ -75,6 +75,7 @@ void FetchEventOpProxyChild::Initialize(
__func__);
mPreloadResponseAvailablePromise->UseSynchronousTaskDispatch(__func__);
if (aArgs.preloadResponse().isSome()) {
+ mPreloadResponseAvailablePromiseResolved = true;
mPreloadResponseAvailablePromise->Resolve(
InternalResponse::FromIPC(aArgs.preloadResponse().ref()), __func__);
}
@@ -91,6 +92,7 @@ void FetchEventOpProxyChild::Initialize(
MakeRefPtr<FetchEventPreloadResponseEndPromise::Private>(__func__);
mPreloadResponseEndPromise->UseSynchronousTaskDispatch(__func__);
if (aArgs.preloadResponseEndArgs().isSome()) {
+ mPreloadResponseEndPromiseResolved = true;
mPreloadResponseEndPromise->Resolve(aArgs.preloadResponseEndArgs().ref(),
__func__);
}
@@ -107,8 +109,8 @@ void FetchEventOpProxyChild::Initialize(
// result until RecvPreloadResponseEnd is called, such that the preload
// response could be completed.
if (self->mPreloadResponseEndPromise &&
- !self->mPreloadResponseEndPromise->IsResolved() &&
- self->mPreloadResponseAvailablePromise->IsResolved()) {
+ !self->mPreloadResponseEndPromiseResolved &&
+ self->mPreloadResponseAvailablePromiseResolved) {
self->mCachedOpResult = Some(aResult);
return;
}
@@ -203,6 +205,7 @@ mozilla::ipc::IPCResult FetchEventOpProxyChild::RecvPreloadResponse(
// Initialize() should have created this promise.
MOZ_ASSERT(mPreloadResponseAvailablePromise);
+ mPreloadResponseAvailablePromiseResolved = true;
mPreloadResponseAvailablePromise->Resolve(
InternalResponse::FromIPC(aResponse), __func__);
@@ -225,6 +228,7 @@ mozilla::ipc::IPCResult FetchEventOpProxyChild::RecvPreloadResponseEnd(
Loading diff…
References
On This Page