From d88b287a63e20e9568878c41a0675cd708223b81 Mon Sep 17 00:00:00 2001 From: David Degazio <35146201+ddegazio@users.noreply.github.com> Date: Tue, 17 Jan 2023 13:47:30 -0800 Subject: [PATCH] Cherry-pick 252432.1031@safari-7614-branch (9f7e401c42a8). https://bugs.webkit.org/show_bug.cgi?id=250429 Fix use-after-free in DFGFixupPhase for array indexOf https://bugs.webkit.org/show_bug.cgi?id=250429 rdar://103852510 Reviewed by Jonathan Bedard and Michael Saboff. During DFG fixup, array indexOf nodes are folded to -1 when the search element is speculated to be a different type than the array element (for instance, JSCell instead of Int32). When this happens, a speculation check is inserted, which can cause the DFG graph's varArgChildren array to reallocate. This invalidates the searchElement Edge reference, which we use immediately after the check insertion in the fixup phase. This patch fixes this potential use-after-free by grabbing the searchElement's associated node before inserting any checks, giving us a persistent pointer to a DFG node rather than a reference into a vector. * JSTests/stress/cell-speculated-array-indexof.js: Added. * Source/JavaScriptCore/dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupArrayIndexOf): Canonical link: https://commits.webkit.org/252432.1031@safari-7614-branch --- JSTests/stress/cell-speculated-array-indexof.js | 10 ++++++++++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | 8 +++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 JSTests/stress/cell-speculated-array-indexof.js diff --git a/JSTests/stress/cell-speculated-array-indexof.js b/JSTests/stress/cell-speculated-array-indexof.js new file mode 100644 index 000000000000..60a61ba2d979 --- /dev/null +++ b/JSTests/stress/cell-speculated-array-indexof.js @@ -0,0 +1,10 @@ +for (let i = 0; i < 10000; ++i) { + const v0 = []; + const v1 = v0.length; + v0[0] %= v1; + const v2 = [0]; + const v3 = v2.slice(v2); + const v4 = v2.indexOf(v3, 0); + const v5 = new Float64Array(0, 0, v1); +} + diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp index dc7c75982123..f928fd531b3f 100644 --- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -4316,24 +4316,26 @@ class FixupPhase : public Phase { switch (node->arrayMode().type()) { case Array::Double: case Array::Int32: { + Node* searchElementNode = searchElement.node(); + if (searchElement->shouldSpeculateCell()) { m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), CellUse)); m_graph.convertToConstant(node, jsNumber(-1)); - observeUseKindOnNode(searchElement.node()); + observeUseKindOnNode(searchElementNode); return; } if (searchElement->shouldSpeculateOther()) { m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), OtherUse)); m_graph.convertToConstant(node, jsNumber(-1)); - observeUseKindOnNode(searchElement.node()); + observeUseKindOnNode(searchElementNode); return; } if (searchElement->shouldSpeculateBoolean()) { m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), BooleanUse)); m_graph.convertToConstant(node, jsNumber(-1)); - observeUseKindOnNode(searchElement.node()); + observeUseKindOnNode(searchElementNode); return; } break;