Firefox · Layout
CVE-2026-117897
Logic Error in Layout
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
iflayout/tables/nsTableFrame.cpp |
modified | |
fortesting/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html |
modified |
Files Changed
layout/tables/nsTableCellFrame.cpplayout/tables/nsTableFrame.cpptesting/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html
Patch
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index 173a8ce74cf..068a9ec3ff3 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -209,7 +209,10 @@ void nsTableCellFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
uint32_t rowIndex = RowIndex();
// row span needs to be clamped as we do not create rows in the cellmap
// which do not have cells originating in them
- TableArea damageArea(colIndex, rowIndex, GetColSpan(),
+ // col span needs to be clamped as the cellmap may not reflect it yet
+ TableArea damageArea(colIndex, rowIndex,
+ std::min(static_cast<uint32_t>(GetColSpan()),
+ tableFrame->GetColCount() - colIndex),
std::min(static_cast<uint32_t>(GetRowSpan()),
tableFrame->GetRowCount() - rowIndex));
tableFrame->AddBCDamageArea(damageArea);
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 04d3e3cde86..645e60758a7 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -4497,10 +4497,11 @@ void nsTableFrame::ExpandBCDamageArea(TableArea& aArea) const {
int32_t numRows = GetRowCount();
int32_t numCols = GetColCount();
- int32_t firstColIdx = aArea.StartCol();
- int32_t lastColIdx = aArea.EndCol() - 1;
- int32_t startRowIdx = aArea.StartRow();
- int32_t endRowIdx = aArea.EndRow() - 1;
+ // Clamp to the table, the damage area can be out of sync with the cell map.
+ int32_t firstColIdx = std::min(aArea.StartCol(), numCols - 1);
+ int32_t lastColIdx = std::min(aArea.EndCol(), numCols) - 1;
+ int32_t startRowIdx = std::min(aArea.StartRow(), numRows - 1);
+ int32_t endRowIdx = std::min(aArea.EndRow(), numRows) - 1;
// expand the damage area in each direction
if (firstColIdx > 0) {
diff --git a/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html b/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html
new file mode 100644
index 00000000000..6d716acb679
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2079036">
+
+<style>
+#d { position: absolute; left: 0; top: 0; }
+table { border-collapse: collapse; }
+td { border: 1px solid black; }
+.x { border-left: 5px solid red; }
+</style>
+
+<div id="d"><table id="t"></table></div>
+
+<script>
+for (let r = 0; r < 7; r++) {
+ let row = t.insertRow();
+ for (let i = 0; i < 15; i++) {
+ row.insertCell().textContent = "a";
+ }
+}
+onload = () => {
+ document.body.offsetWidth;
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ let c = t.rows[3].cells[1];
+ c.colSpan = 60;
+ c.className = "x";
+ t.rows[5].cells[3].firstChild.data = "bbbb";
+ d.style.left = "10px";
+ document.body.offsetWidth;
+ }));
+};
+</script>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html b/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html
new file mode 100644
index 00000000000..6d716acb679
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/crashtests/border-collapse-dynamic-crash.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2079036">
+
+<style>
+#d { position: absolute; left: 0; top: 0; }
+table { border-collapse: collapse; }
+td { border: 1px solid black; }
+.x { border-left: 5px solid red; }
+</style>
+
+<div id="d"><table id="t"></table></div>
+
+<script>
+for (let r = 0; r < 7; r++) {
+ let row = t.insertRow();
+ for (let i = 0; i < 15; i++) {
+ row.insertCell().textContent = "a";
+ }
+}
+onload = () => {
+ document.body.offsetWidth;
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ let c = t.rows[3].cells[1];
+ c.colSpan = 60;
+ c.className = "x";
+ t.rows[5].cells[3].firstChild.data = "bbbb";
+ d.style.left = "10px";
+ document.body.offsetWidth;
+ }));
+};
+</script>
Loading diff…
References
On This Page