Blame SOURCES/CVE-2022-42856.patch

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