Firefox · Layout
CVE-2026-117885
Logic Error in Layout
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
layout/generic/nsGridContainerFrame.cpptesting/web-platform/tests/css/css-grid/observer-chain-crash.html
Patch
diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp
index 35e7c105e69..982c82ac197 100644
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -5752,21 +5752,20 @@ static nscoord MeasuringReflow(nsIFrame* aChild,
nsIFrame::ReflowChildFlags::NoMoveFrame |
nsIFrame::ReflowChildFlags::NoDeleteNextInFlowChild;
- // Reflowing the child might invalidate the cache, so we declare the variable
- // inside the if-statement to ensure it isn't accessed after it may have
- // become invalid.
- if (const GridItemCachedBAxisMeasurement* cachedMeasurement =
+ // NOTE: Reflowing or FinishReflowChild might invalidate the cache.
+ if (const auto* cache =
aChild->GetProperty(GridItemCachedBAxisMeasurement::Prop());
cachedMeasurement && cachedMeasurement->IsValidFor(aChild, aCBSize)) {
- childSize.BSize(wm) = cachedMeasurement->BSize();
+ const nscoord cachedBSize = cachedMeasurement->BSize();
+ childSize.BSize(wm) = cachedBSize;
childSize.ISize(wm) = aChild->ISize(wm);
nsContainerFrame::FinishReflowChild(aChild, pc, childSize, &childRI, wm,
LogicalPoint(wm), nsSize(), flags);
GRID_LOG(
"[perf] MeasuringReflow accepted cached value=%d, child=%p, "
"aCBSize.ISize=%d",
- cachedMeasurement->BSize(), aChild, aCBSize.ISize(wm));
- return cachedMeasurement->BSize();
+ cachedBSize, aChild, aCBSize.ISize(wm));
+ return cachedBSize;
}
parent->ReflowChild(aChild, pc, childSize, childRI, wm, LogicalPoint(wm),
diff --git a/testing/web-platform/tests/css/css-grid/observer-chain-crash.html b/testing/web-platform/tests/css/css-grid/observer-chain-crash.html
new file mode 100644
index 00000000000..ea5a60459e8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-grid/observer-chain-crash.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html class="tets-wait">
+<style>
+#grid{display:grid;grid-template-columns:100px;align-items:start}
+</style>
+<svg width="100" height="40">
+<linearGradient id="paint" href="#item"><stop stop-color="red"/><stop offset="1" stop-color="blue"/></linearGradient>
+<path id="curve" d="M0 0H90V35H0Z" fill="url(#paint)"/>
+</svg>
+<div id="grid"><div id="item"><svg width="70" height="50"><defs><text><textPath href="#curve">x</textPath></text></defs></svg></div><div id="sibling">x</div></div>
+<script>
+async function run() {
+ const grid = document.getElementById("grid");
+ grid.getBoundingClientRect();
+ await new Promise(resolve => requestAnimationFrame(resolve));
+ await new Promise(resolve => setTimeout(resolve, 100));
+ document.getElementById("sibling").firstChild.data += "x";
+ grid.getBoundingClientRect();
+ document.documentElement.className = "";
+}
+run();
+</script>
+</html>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/testing/web-platform/tests/css/css-grid/observer-chain-crash.html b/testing/web-platform/tests/css/css-grid/observer-chain-crash.html
new file mode 100644
index 00000000000..ea5a60459e8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-grid/observer-chain-crash.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html class="tets-wait">
+<style>
+#grid{display:grid;grid-template-columns:100px;align-items:start}
+</style>
+<svg width="100" height="40">
+<linearGradient id="paint" href="#item"><stop stop-color="red"/><stop offset="1" stop-color="blue"/></linearGradient>
+<path id="curve" d="M0 0H90V35H0Z" fill="url(#paint)"/>
+</svg>
+<div id="grid"><div id="item"><svg width="70" height="50"><defs><text><textPath href="#curve">x</textPath></text></defs></svg></div><div id="sibling">x</div></div>
+<script>
+async function run() {
+ const grid = document.getElementById("grid");
+ grid.getBoundingClientRect();
+ await new Promise(resolve => requestAnimationFrame(resolve));
+ await new Promise(resolve => setTimeout(resolve, 100));
+ document.getElementById("sibling").firstChild.data += "x";
+ grid.getBoundingClientRect();
+ document.documentElement.className = "";
+}
+run();
+</script>
+</html>
Loading diff…
References
On This Page