Blame SOURCES/CVE-2022-42856.patch

e0e52e
From 98940f219ba0e3eb6d958af483b73dd9cc75c28c Mon Sep 17 00:00:00 2001
e0e52e
From: Mark Lam <mark.lam@apple.com>
e0e52e
Date: Mon, 19 Dec 2022 17:32:15 -0800
e0e52e
Subject: [PATCH] Cherry-pick 252432.839@safari-7614-branch (71cdc1c09ef1).
e0e52e
 rdar://102531234
e0e52e
e0e52e
    The provenType filtering in FTL's speculateRealNumber is incorrect.
e0e52e
    https://bugs.webkit.org/show_bug.cgi?id=248266
e0e52e
    <rdar://problem/102531234>
e0e52e
e0e52e
    Reviewed by Justin Michaud.
e0e52e
e0e52e
    speculateRealNumber does a doubleEqual compare, which filters out double values which
e0e52e
    are not NaN.  NaN values will fall through to the `intCase` block.  In the `intCase` block,
e0e52e
    the isNotInt32() check there was given a proven type that wrongly filters out ~SpecFullDouble.
e0e52e
e0e52e
    Consider a scenario where the edge was proven to be { SpecInt32Only, SpecDoubleReal,
e0e52e
    SpecDoublePureNaN }.  SpecFullDouble is defined as SpecDoubleReal | SpecDoubleNaN, and
e0e52e
    SpecDoubleNaN is defined as SpecDoublePureNaN | SpecDoubleImpureNaN.  Hence, the filtering
e0e52e
    of the proven type with ~SpecFullDouble means that isNotInt32() will effectively be given
e0e52e
    a proven type of
e0e52e
e0e52e
        { SpecInt32Only, SpecDoubleReal, SpecDoublePureNaN } - { SpecDoubleReal, SpecDoublePureNaN }
e0e52e
e0e52e
    which yields
e0e52e
e0e52e
        { SpecInt32Only }.
e0e52e
e0e52e
    As a result, the compiler will think that that isNotIn32() check will always fail.  This
e0e52e
    is not correct if the actual incoming value for that edge is actually a PureNaN.  In this
e0e52e
    case, speculateRealNumber should have OSR exited, but it doesn't because it thinks that
e0e52e
    the isNotInt32() check will always fail and elide the check altogether.
e0e52e
e0e52e
    In this patch, we fix this by replacing the ~SpecFullDouble with ~SpecDoubleReal.  We also
e0e52e
    rename the `intCase` block to `intOrNaNCase` to document what it actually handles.
e0e52e
e0e52e
    * JSTests/stress/speculate-real-number-in-object-is.js: Added.
e0e52e
    (test.object_is_opt):
e0e52e
    (test):
e0e52e
    * Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
e0e52e
    (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
e0e52e
e0e52e
    Canonical link: https://commits.webkit.org/252432.839@safari-7614-branch
e0e52e
e0e52e
Canonical link: https://commits.webkit.org/258113@main
e0e52e
---
e0e52e
 .../speculate-real-number-in-object-is.js     | 22 +++++++++++++++++++
e0e52e
 Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp |  8 +++----
e0e52e
 2 files changed, 26 insertions(+), 4 deletions(-)
e0e52e
 create mode 100644 JSTests/stress/speculate-real-number-in-object-is.js
e0e52e
e0e52e
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
e0e52e
index 3ba2d21b8072..18d13f1941bb 100644
e0e52e
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
e0e52e
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
e0e52e
@@ -20574,18 +20574,18 @@ IGNORE_CLANG_WARNINGS_END
e0e52e
         LValue value = lowJSValue(edge, ManualOperandSpeculation);
e0e52e
         LValue doubleValue = unboxDouble(value);
e0e52e
         
e0e52e
-        LBasicBlock intCase = m_out.newBlock();
e0e52e
+        LBasicBlock intOrNaNCase = m_out.newBlock();
e0e52e
         LBasicBlock continuation = m_out.newBlock();
e0e52e
         
e0e52e
         m_out.branch(
e0e52e
             m_out.doubleEqual(doubleValue, doubleValue),
e0e52e
-            usually(continuation), rarely(intCase));
e0e52e
+            usually(continuation), rarely(intOrNaNCase));
e0e52e
         
e0e52e
-        LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
e0e52e
+        LBasicBlock lastNext = m_out.appendTo(intOrNaNCase, continuation);
e0e52e
         
e0e52e
         typeCheck(
e0e52e
             jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
e0e52e
-            isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble));
e0e52e
+            isNotInt32(value, provenType(m_node->child1()) & ~SpecDoubleReal));
e0e52e
         m_out.jump(continuation);
e0e52e
 
e0e52e
         m_out.appendTo(continuation, lastNext);