Firefox · DOM
CVE-2026-117918
Logic Error in DOM
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/canvas/OffscreenCanvasDisplayHelper.cpp |
modified | |
GetCanvasForWorkerdom/canvas/OffscreenCanvasDisplayHelper.cpp |
modified | |
mDisplayHelperdom/canvas/OffscreenCanvasDisplayHelper.cpp |
modified |
Files Changed
dom/canvas/OffscreenCanvasDisplayHelper.cppdom/canvas/OffscreenCanvasDisplayHelper.h
Patch
diff --git a/dom/canvas/OffscreenCanvasDisplayHelper.cpp b/dom/canvas/OffscreenCanvasDisplayHelper.cpp
index 65fdd703a35..cc5c8ad787a 100644
--- a/dom/canvas/OffscreenCanvasDisplayHelper.cpp
+++ b/dom/canvas/OffscreenCanvasDisplayHelper.cpp
@@ -120,6 +120,13 @@ RefPtr<layers::ImageContainer> OffscreenCanvasDisplayHelper::GetImageContainer()
bool OffscreenCanvasDisplayHelper::MayUpdateContext(WorkerPrivate* aWorker,
ErrorResult& aRv) {
MutexAutoLock lock(mMutex);
+ // Allow context update on main thread to be more fault tolerant, whereas
+ // update on a worker needs to more strict in case of transfer.
+ if ((mCreatedOnMainThread && aWorker) || mCreatedOnWorker) {
+ aRv.ThrowInvalidStateError(
+ "Cannot update created context to different thread");
+ return false;
+ }
if (!mOffscreenCanvas) {
return true;
}
@@ -153,6 +160,14 @@ void OffscreenCanvasDisplayHelper::UpdateContext(
mType = aType;
mContextChildId = aChildId;
+ if (mOffscreenCanvas) {
+ if (mWorkerRef) {
+ mCreatedOnWorker = true;
+ } else {
+ mCreatedOnMainThread = true;
+ }
+ }
+
if (aChildId) {
mContextManagerId = Some(gfx::CanvasManagerChild::Get()->Id());
} else {
@@ -162,6 +177,16 @@ void OffscreenCanvasDisplayHelper::UpdateContext(
MaybeQueueInvalidateElement();
}
+already_AddRefed<OffscreenCanvas>
+OffscreenCanvasDisplayHelper::GetCanvasForWorker(WorkerPrivate* aWorker) {
+ MutexAutoLock lock(mMutex);
+ // A runnable queued to a worker somehow got assigned to another thread.
+ if (NS_WARN_IF(!mWorkerRef) || NS_WARN_IF(mWorkerRef->Private() != aWorker)) {
+ return nullptr;
+ }
+ return do_AddRef(mOffscreenCanvas);
+}
+
void OffscreenCanvasDisplayHelper::FlushForDisplay() {
MOZ_ASSERT(NS_IsMainThread());
@@ -189,17 +214,14 @@ void OffscreenCanvasDisplayHelper::FlushForDisplay() {
: MainThreadWorkerRunnable("FlushWorkerRunnable"),
mDisplayHelper(aDisplayHelper) {}
- bool WorkerRun(JSContext*, WorkerPrivate*) override {
+ bool WorkerRun(JSContext*, WorkerPrivate* aWorkerPrivate) override {
// The OffscreenCanvas can only be freed on the worker thread, so we
// cannot be racing with an OffscreenCanvas::DestroyCanvas call and its
// destructor. We just need to make sure we don't call into
// OffscreenCanvas while holding the lock since it calls back into the
// OffscreenCanvasDisplayHelper.
- RefPtr<OffscreenCanvas> canvas;
- {
- MutexAutoLock lock(mDisplayHelper->mMutex);
- canvas = mDisplayHelper->mOffscreenCanvas;
- }
+ RefPtr<OffscreenCanvas> canvas =
+ mDisplayHelper->GetCanvasForWorker(aWorkerPrivate);
if (canvas) {
canvas->CommitFrameToCompositor();
@@ -513,17 +535,14 @@ OffscreenCanvasDisplayHelper::GetSurfaceSnapshot() {
mMonitor("SnapshotWorkerRunnable::mMonitor"),
mDisplayHelper(aDisplayHelper) {}
- bool WorkerRun(JSContext*, WorkerPrivate*) override {
+ bool WorkerRun(JSContext*, WorkerPrivate* aWorkerPrivate) override {
// The OffscreenCanvas can only be freed on the worker thread, so we
// cannot be racing with an OffscreenCanvas::DestroyCanvas call and its
// destructor. We just need to make sure we don't call into
// OffscreenCanvas while holding the lock since it calls back into the
// OffscreenCanvasDisplayHelper.
- RefPtr<OffscreenCanvas> canvas;
- {
- MutexAutoLock lock(mDisplayHelper->mMutex);
- canvas = mDisplayHelper->mOffscreenCanvas;
- }
+ RefPtr<OffscreenCanvas> canvas =
+ mDisplayHelper->GetCanvasForWorker(aWorkerPrivate);
// Now that we are on the correct thread, we can extract the snapshot. If
// it is a Skia surface, perform a copy to threading issues.
diff --git a/dom/canvas/OffscreenCanvasDisplayHelper.h b/dom/canvas/OffscreenCanvasDisplayHelper.h
index 72d6e4a5b78..f7db258e2e1 100644
--- a/dom/canvas/OffscreenCanvasDisplayHelper.h
+++ b/dom/canvas/OffscreenCanvasDisplayHelper.h
@@ -89,6 +89,7 @@ class OffscreenCanvasDisplayHelper final {
private:
~OffscreenCanvasDisplayHelper();
void MaybeQueueInvalidateElement() MOZ_REQUIRES(mMutex);
+ already_AddRefed<OffscreenCanvas> GetCanvasForWorker(WorkerPrivate* aWorker);
void InvalidateElement();
already_AddRefed<gfx::SourceSurface> TransformSurface(
@@ -115,6 +116,8 @@ class OffscreenCanvasDisplayHelper final {
bool mPendingPresent MOZ_GUARDED_BY(mMutex) = false;
bool mIsWriteOnly MOZ_GUARDED_BY(mMutex) = false;
RefPtr<nsIPrincipal> mExpandedReader MOZ_GUARDED_BY(mMutex);
+ bool mCreatedOnMainThread MOZ_GUARDED_BY(mMutex) = false;
+ bool mCreatedOnWorker MOZ_GUARDED_BY(mMutex) = false;
};
} // namespace mozilla::dom
Loading diff…
References
On This Page