Blame SOURCES/CVE-2023-28205.patch

477a3b
From 1039f0c3235ffd9a6584657adb34db10c562e4af Mon Sep 17 00:00:00 2001
477a3b
From: Mark Lam <mark.lam@apple.com>
477a3b
Date: Fri, 31 Mar 2023 10:49:49 -0700
477a3b
Subject: [PATCH] Cherry-pick 2c49ff7b0481. rdar://problem/107369977
477a3b
477a3b
    CloneDeserializer::deserialize() should store cell pointers in a MarkedVector.
477a3b
    https://bugs.webkit.org/show_bug.cgi?id=254797
477a3b
    rdar://107369977
477a3b
477a3b
    Reviewed by Justin Michaud.
477a3b
477a3b
    Previously, CloneDeserializer::deserialize() was storing pointers to newly created objects
477a3b
    in a few Vectors.  This is problematic because the GC is not aware of Vectors, and cannot
477a3b
    scan them.  In this patch, we refactor the MarkedArgumentBuffer class into a MarkedVector
477a3b
    template class that offer 2 enhancements:
477a3b
477a3b
    1. It can be configured to store specific types of cell pointer types.  This avoids us
477a3b
       having to constantly cast JSValues into these pointers.
477a3b
477a3b
    2. It allows us to specify the type of OverflowHandler we want to use.  In this case,
477a3b
       we want to use CrashOnOverflow.  The previous MarkedArgumentBuffer always assumes
477a3b
       RecordOnOverflow.  This allows us to avoid having to manually check for overflows,
477a3b
       or have to use appendWithCrashOnOverflow.  For our current needs, MarkedVector can be
477a3b
       used as a drop in replacement for Vector.
477a3b
477a3b
    And we fix the CloneDeserializer::deserialize() issue by replacing the use of Vectors
477a3b
    with MarkedVector instead.
477a3b
477a3b
    * Source/JavaScriptCore/heap/Heap.cpp:
477a3b
    (JSC::Heap::addCoreConstraints):
477a3b
    * Source/JavaScriptCore/heap/Heap.h:
477a3b
    * Source/JavaScriptCore/heap/HeapInlines.h:
477a3b
    * Source/JavaScriptCore/runtime/ArgList.cpp:
477a3b
    (JSC::MarkedVectorBase::addMarkSet):
477a3b
    (JSC::MarkedVectorBase::markLists):
477a3b
    (JSC::MarkedVectorBase::slowEnsureCapacity):
477a3b
    (JSC::MarkedVectorBase::expandCapacity):
477a3b
    (JSC::MarkedVectorBase::slowAppend):
477a3b
    (JSC::MarkedArgumentBufferBase::addMarkSet): Deleted.
477a3b
    (JSC::MarkedArgumentBufferBase::markLists): Deleted.
477a3b
    (JSC::MarkedArgumentBufferBase::slowEnsureCapacity): Deleted.
477a3b
    (JSC::MarkedArgumentBufferBase::expandCapacity): Deleted.
477a3b
    (JSC::MarkedArgumentBufferBase::slowAppend): Deleted.
477a3b
    * Source/JavaScriptCore/runtime/ArgList.h:
477a3b
    (JSC::MarkedVectorWithSize::MarkedVectorWithSize):
477a3b
    (JSC::MarkedVectorWithSize::at const):
477a3b
    (JSC::MarkedVectorWithSize::clear):
477a3b
    (JSC::MarkedVectorWithSize::append):
477a3b
    (JSC::MarkedVectorWithSize::appendWithCrashOnOverflow):
477a3b
    (JSC::MarkedVectorWithSize::last const):
477a3b
    (JSC::MarkedVectorWithSize::takeLast):
477a3b
    (JSC::MarkedVectorWithSize::ensureCapacity):
477a3b
    (JSC::MarkedVectorWithSize::hasOverflowed):
477a3b
    (JSC::MarkedVectorWithSize::fill):
477a3b
    (JSC::MarkedArgumentBufferWithSize::MarkedArgumentBufferWithSize): Deleted.
477a3b
    * Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp:
477a3b
    (WebCore::AudioWorkletProcessor::buildJSArguments):
477a3b
    * Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:
477a3b
    * Source/WebCore/bindings/js/SerializedScriptValue.cpp:
477a3b
    (WebCore::CloneDeserializer::deserialize):
477a3b
477a3b
    Canonical link: https://commits.webkit.org/259548.530@safari-7615-branch
477a3b
477a3b
Identifier: 259548.395@safari-7615.1.26.11-branch
477a3b
---
477a3b
 Source/JavaScriptCore/heap/Heap.cpp           |   4 +-
477a3b
 Source/JavaScriptCore/heap/Heap.h             |   8 +-
477a3b
 Source/JavaScriptCore/heap/HeapInlines.h      |   2 +-
477a3b
 Source/JavaScriptCore/runtime/ArgList.cpp     |  46 ++--
477a3b
 Source/JavaScriptCore/runtime/ArgList.h       | 206 ++++++++++--------
477a3b
 .../webaudio/AudioWorkletProcessor.cpp        |   4 +-
477a3b
 .../Modules/webaudio/AudioWorkletProcessor.h  |   7 +-
477a3b
 .../bindings/js/SerializedScriptValue.cpp     |  11 +-
477a3b
 8 files changed, 158 insertions(+), 130 deletions(-)
477a3b
477a3b
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
477a3b
index d773eb9e79d6..37bf0e94b266 100644
477a3b
--- a/Source/JavaScriptCore/heap/Heap.cpp
477a3b
+++ b/Source/JavaScriptCore/heap/Heap.cpp
477a3b
@@ -1,5 +1,5 @@
477a3b
 /*
477a3b
- *  Copyright (C) 2003-2022 Apple Inc. All rights reserved.
477a3b
+ *  Copyright (C) 2003-2023 Apple Inc. All rights reserved.
477a3b
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
477a3b
  *
477a3b
  *  This library is free software; you can redistribute it and/or
477a3b
@@ -2854,7 +2854,7 @@ void Heap::addCoreConstraints()
477a3b
             
477a3b
             if (!m_markListSet.isEmpty()) {
477a3b
                 SetRootMarkReasonScope rootScope(visitor, RootMarkReason::ConservativeScan);
477a3b
-                MarkedArgumentBufferBase::markLists(visitor, m_markListSet);
477a3b
+                MarkedVectorBase::markLists(visitor, m_markListSet);
477a3b
             }
477a3b
 
477a3b
             {
477a3b
diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h
477a3b
index d6cb99c4e4b5..315d62e50b1d 100644
477a3b
--- a/Source/JavaScriptCore/heap/Heap.h
477a3b
+++ b/Source/JavaScriptCore/heap/Heap.h
477a3b
@@ -1,7 +1,7 @@
477a3b
 /*
477a3b
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
477a3b
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
477a3b
- *  Copyright (C) 2003-2022 Apple Inc. All rights reserved.
477a3b
+ *  Copyright (C) 2003-2023 Apple Inc. All rights reserved.
477a3b
  *
477a3b
  *  This library is free software; you can redistribute it and/or
477a3b
  *  modify it under the terms of the GNU Lesser General Public
477a3b
@@ -85,7 +85,7 @@ class MarkStackArray;
477a3b
 class MarkStackMergingConstraint;
477a3b
 class MarkedJSValueRefArray;
477a3b
 class BlockDirectory;
477a3b
-class MarkedArgumentBufferBase;
477a3b
+class MarkedVectorBase;
477a3b
 class MarkingConstraint;
477a3b
 class MarkingConstraintSet;
477a3b
 class MutatorScheduler;
477a3b
@@ -413,7 +413,7 @@ class Heap {
477a3b
     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> protectedObjectTypeCounts();
477a3b
     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> objectTypeCounts();
477a3b
 
477a3b
-    HashSet<MarkedArgumentBufferBase*>& markListSet();
477a3b
+    HashSet<MarkedVectorBase*>& markListSet();
477a3b
     void addMarkedJSValueRefArray(MarkedJSValueRefArray*);
477a3b
     
477a3b
     template<typename Functor> void forEachProtectedCell(const Functor&);
477a3b
@@ -782,7 +782,7 @@ class Heap {
477a3b
     size_t m_deprecatedExtraMemorySize { 0 };
477a3b
 
477a3b
     ProtectCountSet m_protectedValues;
477a3b
-    HashSet<MarkedArgumentBufferBase*> m_markListSet;
477a3b
+    HashSet<MarkedVectorBase*> m_markListSet;
477a3b
     SentinelLinkedList<MarkedJSValueRefArray, BasicRawSentinelNode<MarkedJSValueRefArray>> m_markedJSValueRefArrays;
477a3b
 
477a3b
     std::unique_ptr<MachineThreads> m_machineThreads;
477a3b
diff --git a/Source/JavaScriptCore/heap/HeapInlines.h b/Source/JavaScriptCore/heap/HeapInlines.h
477a3b
index f91546bb62c4..8e33eaae4a4f 100644
477a3b
--- a/Source/JavaScriptCore/heap/HeapInlines.h
477a3b
+++ b/Source/JavaScriptCore/heap/HeapInlines.h
477a3b
@@ -205,7 +205,7 @@ inline void Heap::decrementDeferralDepthAndGCIfNeeded()
477a3b
     }
477a3b
 }
477a3b
 
477a3b
-inline HashSet<MarkedArgumentBufferBase*>& Heap::markListSet()
477a3b
+inline HashSet<MarkedVectorBase*>& Heap::markListSet()
477a3b
 {
477a3b
     return m_markListSet;
477a3b
 }
477a3b
diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp
477a3b
index f2815b80c8c7..a72dea74a56f 100644
477a3b
--- a/Source/JavaScriptCore/runtime/ArgList.cpp
477a3b
+++ b/Source/JavaScriptCore/runtime/ArgList.cpp
477a3b
@@ -1,5 +1,5 @@
477a3b
 /*
477a3b
- *  Copyright (C) 2003-2021 Apple Inc. All rights reserved.
477a3b
+ *  Copyright (C) 2003-2023 Apple Inc. All rights reserved.
477a3b
  *
477a3b
  *  This library is free software; you can redistribute it and/or
477a3b
  *  modify it under the terms of the GNU Library General Public
477a3b
@@ -27,7 +27,7 @@ using std::min;
477a3b
 
477a3b
 namespace JSC {
477a3b
 
477a3b
-void MarkedArgumentBufferBase::addMarkSet(JSValue v)
477a3b
+void MarkedVectorBase::addMarkSet(JSValue v)
477a3b
 {
477a3b
     if (m_markSet)
477a3b
         return;
477a3b
@@ -52,47 +52,47 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
477a3b
 }
477a3b
 
477a3b
 template<typename Visitor>
477a3b
-void MarkedArgumentBufferBase::markLists(Visitor& visitor, ListSet& markSet)
477a3b
+void MarkedVectorBase::markLists(Visitor& visitor, ListSet& markSet)
477a3b
 {
477a3b
     ListSet::iterator end = markSet.end();
477a3b
     for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
477a3b
-        MarkedArgumentBufferBase* list = *it;
477a3b
+        MarkedVectorBase* list = *it;
477a3b
         for (int i = 0; i < list->m_size; ++i)
477a3b
             visitor.appendUnbarriered(JSValue::decode(list->slotFor(i)));
477a3b
     }
477a3b
 }
477a3b
 
477a3b
-template void MarkedArgumentBufferBase::markLists(AbstractSlotVisitor&, ListSet&);
477a3b
-template void MarkedArgumentBufferBase::markLists(SlotVisitor&, ListSet&);
477a3b
+template void MarkedVectorBase::markLists(AbstractSlotVisitor&, ListSet&);
477a3b
+template void MarkedVectorBase::markLists(SlotVisitor&, ListSet&);
477a3b
 
477a3b
-void MarkedArgumentBufferBase::slowEnsureCapacity(size_t requestedCapacity)
477a3b
+auto MarkedVectorBase::slowEnsureCapacity(size_t requestedCapacity) -> Status
477a3b
 {
477a3b
     setNeedsOverflowCheck();
477a3b
     auto checkedNewCapacity = CheckedInt32(requestedCapacity);
477a3b
     if (UNLIKELY(checkedNewCapacity.hasOverflowed()))
477a3b
-        return this->overflowed();
477a3b
-    expandCapacity(checkedNewCapacity);
477a3b
+        return Status::Overflowed;
477a3b
+    return expandCapacity(checkedNewCapacity);
477a3b
 }
477a3b
 
477a3b
-void MarkedArgumentBufferBase::expandCapacity()
477a3b
+auto MarkedVectorBase::expandCapacity() -> Status
477a3b
 {
477a3b
     setNeedsOverflowCheck();
477a3b
     auto checkedNewCapacity = CheckedInt32(m_capacity) * 2;
477a3b
     if (UNLIKELY(checkedNewCapacity.hasOverflowed()))
477a3b
-        return this->overflowed();
477a3b
-    expandCapacity(checkedNewCapacity);
477a3b
+        return Status::Overflowed;
477a3b
+    return expandCapacity(checkedNewCapacity);
477a3b
 }
477a3b
 
477a3b
-void MarkedArgumentBufferBase::expandCapacity(int newCapacity)
477a3b
+auto MarkedVectorBase::expandCapacity(int newCapacity) -> Status
477a3b
 {
477a3b
     setNeedsOverflowCheck();
477a3b
     ASSERT(m_capacity < newCapacity);
477a3b
     auto checkedSize = CheckedSize(newCapacity) * sizeof(EncodedJSValue);
477a3b
     if (UNLIKELY(checkedSize.hasOverflowed()))
477a3b
-        return this->overflowed();
477a3b
+        return Status::Overflowed;
477a3b
     EncodedJSValue* newBuffer = static_cast<EncodedJSValue*>(Gigacage::tryMalloc(Gigacage::JSValue, checkedSize));
477a3b
     if (!newBuffer)
477a3b
-        return this->overflowed();
477a3b
+        return Status::Overflowed;
477a3b
     for (int i = 0; i < m_size; ++i) {
477a3b
         newBuffer[i] = m_buffer[i];
477a3b
         addMarkSet(JSValue::decode(m_buffer[i]));
477a3b
@@ -103,21 +103,23 @@ void MarkedArgumentBufferBase::expandCapacity(int newCapacity)
477a3b
 
477a3b
     m_buffer = newBuffer;
477a3b
     m_capacity = newCapacity;
477a3b
+    return Status::Success;
477a3b
 }
477a3b
 
477a3b
-void MarkedArgumentBufferBase::slowAppend(JSValue v)
477a3b
+auto MarkedVectorBase::slowAppend(JSValue v) -> Status
477a3b
 {
477a3b
     ASSERT(m_size <= m_capacity);
477a3b
-    if (m_size == m_capacity)
477a3b
-        expandCapacity();
477a3b
-    if (UNLIKELY(Base::hasOverflowed())) {
477a3b
-        ASSERT(m_needsOverflowCheck);
477a3b
-        return;
477a3b
+    if (m_size == m_capacity) {
477a3b
+        auto status = expandCapacity();
477a3b
+        if (status == Status::Overflowed) {
477a3b
+            ASSERT(m_needsOverflowCheck);
477a3b
+            return status;
477a3b
+        }
477a3b
     }
477a3b
-
477a3b
     slotFor(m_size) = JSValue::encode(v);
477a3b
     ++m_size;
477a3b
     addMarkSet(v);
477a3b
+    return Status::Success;
477a3b
 }
477a3b
 
477a3b
 } // namespace JSC
477a3b
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h
477a3b
index 8ea9b0e308b8..07632263266b 100644
477a3b
--- a/Source/JavaScriptCore/runtime/ArgList.h
477a3b
+++ b/Source/JavaScriptCore/runtime/ArgList.h
477a3b
@@ -28,20 +28,20 @@
477a3b
 
477a3b
 namespace JSC {
477a3b
 
477a3b
-class alignas(alignof(EncodedJSValue)) MarkedArgumentBufferBase : public RecordOverflow {
477a3b
-    WTF_MAKE_NONCOPYABLE(MarkedArgumentBufferBase);
477a3b
-    WTF_MAKE_NONMOVABLE(MarkedArgumentBufferBase);
477a3b
+class alignas(alignof(EncodedJSValue)) MarkedVectorBase {
477a3b
+    WTF_MAKE_NONCOPYABLE(MarkedVectorBase);
477a3b
+    WTF_MAKE_NONMOVABLE(MarkedVectorBase);
477a3b
     WTF_FORBID_HEAP_ALLOCATION;
477a3b
     friend class VM;
477a3b
     friend class ArgList;
477a3b
 
477a3b
+protected:
477a3b
+    enum class Status { Success, Overflowed };
477a3b
 public:
477a3b
-    using Base = RecordOverflow;
477a3b
-    typedef HashSet<MarkedArgumentBufferBase*> ListSet;
477a3b
+    typedef HashSet<MarkedVectorBase*> ListSet;
477a3b
 
477a3b
-    ~MarkedArgumentBufferBase()
477a3b
+    ~MarkedVectorBase()
477a3b
     {
477a3b
-        ASSERT(!m_needsOverflowCheck);
477a3b
         if (m_markSet)
477a3b
             m_markSet->remove(this);
477a3b
 
477a3b
@@ -52,92 +52,20 @@ class alignas(alignof(EncodedJSValue)) MarkedArgumentBufferBase : public RecordO
477a3b
     size_t size() const { return m_size; }
477a3b
     bool isEmpty() const { return !m_size; }
477a3b
 
477a3b
-    JSValue at(int i) const
477a3b
-    {
477a3b
-        if (i >= m_size)
477a3b
-            return jsUndefined();
477a3b
-
477a3b
-        return JSValue::decode(slotFor(i));
477a3b
-    }
477a3b
-
477a3b
-    void clear()
477a3b
-    {
477a3b
-        ASSERT(!m_needsOverflowCheck);
477a3b
-        clearOverflow();
477a3b
-        m_size = 0;
477a3b
-    }
477a3b
-
477a3b
-    enum OverflowCheckAction {
477a3b
-        CrashOnOverflow,
477a3b
-        WillCheckLater
477a3b
-    };
477a3b
-    template<OverflowCheckAction action>
477a3b
-    void appendWithAction(JSValue v)
477a3b
-    {
477a3b
-        ASSERT(m_size <= m_capacity);
477a3b
-        if (m_size == m_capacity || mallocBase()) {
477a3b
-            slowAppend(v);
477a3b
-            if (action == CrashOnOverflow)
477a3b
-                RELEASE_ASSERT(!hasOverflowed());
477a3b
-            return;
477a3b
-        }
477a3b
-
477a3b
-        slotFor(m_size) = JSValue::encode(v);
477a3b
-        ++m_size;
477a3b
-    }
477a3b
-    void append(JSValue v) { appendWithAction<WillCheckLater>(v); }
477a3b
-    void appendWithCrashOnOverflow(JSValue v) { appendWithAction<CrashOnOverflow>(v); }
477a3b
-
477a3b
     void removeLast()
477a3b
     { 
477a3b
         ASSERT(m_size);
477a3b
         m_size--;
477a3b
     }
477a3b
 
477a3b
-    JSValue last() 
477a3b
-    {
477a3b
-        ASSERT(m_size);
477a3b
-        return JSValue::decode(slotFor(m_size - 1));
477a3b
-    }
477a3b
-
477a3b
-    JSValue takeLast()
477a3b
-    {
477a3b
-        JSValue result = last();
477a3b
-        removeLast();
477a3b
-        return result;
477a3b
-    }
477a3b
-        
477a3b
     template<typename Visitor> static void markLists(Visitor&, ListSet&);
477a3b
 
477a3b
-    void ensureCapacity(size_t requestedCapacity)
477a3b
-    {
477a3b
-        if (requestedCapacity > static_cast<size_t>(m_capacity))
477a3b
-            slowEnsureCapacity(requestedCapacity);
477a3b
-    }
477a3b
-
477a3b
-    bool hasOverflowed()
477a3b
-    {
477a3b
-        clearNeedsOverflowCheck();
477a3b
-        return Base::hasOverflowed();
477a3b
-    }
477a3b
-
477a3b
     void overflowCheckNotNeeded() { clearNeedsOverflowCheck(); }
477a3b
 
477a3b
-    template<typename Functor>
477a3b
-    void fill(size_t count, const Functor& func)
477a3b
-    {
477a3b
-        ASSERT(!m_size);
477a3b
-        ensureCapacity(count);
477a3b
-        if (Base::hasOverflowed())
477a3b
-            return;
477a3b
-        m_size = count;
477a3b
-        func(reinterpret_cast<JSValue*>(&slotFor(0)));
477a3b
-    }
477a3b
-
477a3b
 protected:
477a3b
     // Constructor for a read-write list, to which you may append values.
477a3b
     // FIXME: Remove all clients of this API, then remove this API.
477a3b
-    MarkedArgumentBufferBase(size_t capacity)
477a3b
+    MarkedVectorBase(size_t capacity)
477a3b
         : m_size(0)
477a3b
         , m_capacity(capacity)
477a3b
         , m_buffer(inlineBuffer())
477a3b
@@ -147,17 +75,16 @@ class alignas(alignof(EncodedJSValue)) MarkedArgumentBufferBase : public RecordO
477a3b
 
477a3b
     EncodedJSValue* inlineBuffer()
477a3b
     {
477a3b
-        return bitwise_cast<EncodedJSValue*>(bitwise_cast<uint8_t*>(this) + sizeof(MarkedArgumentBufferBase));
477a3b
+        return bitwise_cast<EncodedJSValue*>(bitwise_cast<uint8_t*>(this) + sizeof(MarkedVectorBase));
477a3b
     }
477a3b
 
477a3b
-private:
477a3b
-    void expandCapacity();
477a3b
-    void expandCapacity(int newCapacity);
477a3b
-    void slowEnsureCapacity(size_t requestedCapacity);
477a3b
+    Status expandCapacity();
477a3b
+    Status expandCapacity(int newCapacity);
477a3b
+    Status slowEnsureCapacity(size_t requestedCapacity);
477a3b
 
477a3b
     void addMarkSet(JSValue);
477a3b
 
477a3b
-    JS_EXPORT_PRIVATE void slowAppend(JSValue);
477a3b
+    JS_EXPORT_PRIVATE Status slowAppend(JSValue);
477a3b
 
477a3b
     EncodedJSValue& slotFor(int item) const
477a3b
     {
477a3b
@@ -172,11 +99,14 @@ class alignas(alignof(EncodedJSValue)) MarkedArgumentBufferBase : public RecordO
477a3b
     }
477a3b
 
477a3b
 #if ASSERT_ENABLED
477a3b
-    void setNeedsOverflowCheck() { m_needsOverflowCheck = true; }
477a3b
+    void disableNeedsOverflowCheck() { m_overflowCheckEnabled = false; }
477a3b
+    void setNeedsOverflowCheck() { m_needsOverflowCheck = m_overflowCheckEnabled; }
477a3b
     void clearNeedsOverflowCheck() { m_needsOverflowCheck = false; }
477a3b
 
477a3b
     bool m_needsOverflowCheck { false };
477a3b
+    bool m_overflowCheckEnabled { true };
477a3b
 #else
477a3b
+    void disableNeedsOverflowCheck() { }
477a3b
     void setNeedsOverflowCheck() { }
477a3b
     void clearNeedsOverflowCheck() { }
477a3b
 #endif // ASSERT_ENABLED
477a3b
@@ -186,22 +116,114 @@ class alignas(alignof(EncodedJSValue)) MarkedArgumentBufferBase : public RecordO
477a3b
     ListSet* m_markSet;
477a3b
 };
477a3b
 
477a3b
-template<size_t passedInlineCapacity = 8>
477a3b
-class MarkedArgumentBufferWithSize : public MarkedArgumentBufferBase {
477a3b
+template<typename T, size_t passedInlineCapacity = 8, class OverflowHandler = CrashOnOverflow>
477a3b
+class MarkedVector : public OverflowHandler, public MarkedVectorBase  {
477a3b
 public:
477a3b
     static constexpr size_t inlineCapacity = passedInlineCapacity;
477a3b
 
477a3b
-    MarkedArgumentBufferWithSize()
477a3b
-        : MarkedArgumentBufferBase(inlineCapacity)
477a3b
+    MarkedVector()
477a3b
+        : MarkedVectorBase(inlineCapacity)
477a3b
     {
477a3b
         ASSERT(inlineBuffer() == m_inlineBuffer);
477a3b
+        if constexpr (std::is_same_v<OverflowHandler, CrashOnOverflow>) {
477a3b
+            // CrashOnOverflow handles overflows immediately. So, we do not
477a3b
+            // need to check for it after.
477a3b
+            disableNeedsOverflowCheck();
477a3b
+        }
477a3b
+    }
477a3b
+
477a3b
+    auto at(int i) const -> decltype(auto)
477a3b
+    {
477a3b
+        if constexpr (std::is_same_v<T, JSValue>) {
477a3b
+            if (i >= m_size)
477a3b
+                return jsUndefined();
477a3b
+            return JSValue::decode(slotFor(i));
477a3b
+        } else {
477a3b
+            if (i >= m_size)
477a3b
+                return static_cast<T>(nullptr);
477a3b
+            return jsCast<T>(JSValue::decode(slotFor(i)).asCell());
477a3b
+        }
477a3b
+    }
477a3b
+
477a3b
+    void clear()
477a3b
+    {
477a3b
+        ASSERT(!m_needsOverflowCheck);
477a3b
+        OverflowHandler::clearOverflow();
477a3b
+        m_size = 0;
477a3b
+    }
477a3b
+
477a3b
+    void append(T v)
477a3b
+    {
477a3b
+        ASSERT(m_size <= m_capacity);
477a3b
+        if (m_size == m_capacity || mallocBase()) {
477a3b
+            if (slowAppend(v) == Status::Overflowed)
477a3b
+                this->overflowed();
477a3b
+            return;
477a3b
+        }
477a3b
+
477a3b
+        slotFor(m_size) = JSValue::encode(v);
477a3b
+        ++m_size;
477a3b
+    }
477a3b
+
477a3b
+    void appendWithCrashOnOverflow(T v)
477a3b
+    {
477a3b
+        append(v);
477a3b
+        if constexpr (!std::is_same<OverflowHandler, CrashOnOverflow>::value)
477a3b
+            RELEASE_ASSERT(!this->hasOverflowed());
477a3b
+    }
477a3b
+
477a3b
+    auto last() const -> decltype(auto)
477a3b
+    {
477a3b
+        if constexpr (std::is_same_v<T, JSValue>) {
477a3b
+            ASSERT(m_size);
477a3b
+            return JSValue::decode(slotFor(m_size - 1));
477a3b
+        } else {
477a3b
+            ASSERT(m_size);
477a3b
+            return jsCast<T>(JSValue::decode(slotFor(m_size - 1)).asCell());
477a3b
+        }
477a3b
+    }
477a3b
+
477a3b
+    JSValue takeLast()
477a3b
+    {
477a3b
+        JSValue result = last();
477a3b
+        removeLast();
477a3b
+        return result;
477a3b
+    }
477a3b
+
477a3b
+    void ensureCapacity(size_t requestedCapacity)
477a3b
+    {
477a3b
+        if (requestedCapacity > static_cast<size_t>(m_capacity)) {
477a3b
+            if (slowEnsureCapacity(requestedCapacity) == Status::Overflowed)
477a3b
+                this->overflowed();
477a3b
+        }
477a3b
+    }
477a3b
+
477a3b
+    bool hasOverflowed()
477a3b
+    {
477a3b
+        clearNeedsOverflowCheck();
477a3b
+        return OverflowHandler::hasOverflowed();
477a3b
+    }
477a3b
+
477a3b
+    template<typename Functor>
477a3b
+    void fill(size_t count, const Functor& func)
477a3b
+    {
477a3b
+        ASSERT(!m_size);
477a3b
+        ensureCapacity(count);
477a3b
+        if (OverflowHandler::hasOverflowed())
477a3b
+            return;
477a3b
+        m_size = count;
477a3b
+        func(reinterpret_cast<JSValue*>(&slotFor(0)));
477a3b
     }
477a3b
 
477a3b
 private:
477a3b
     EncodedJSValue m_inlineBuffer[inlineCapacity] { };
477a3b
 };
477a3b
 
477a3b
-using MarkedArgumentBuffer = MarkedArgumentBufferWithSize<>;
477a3b
+template<size_t passedInlineCapacity>
477a3b
+class MarkedArgumentBufferWithSize : public MarkedVector<JSValue, passedInlineCapacity, RecordOverflow> {
477a3b
+};
477a3b
+
477a3b
+using MarkedArgumentBuffer = MarkedVector<JSValue, 8, RecordOverflow>;
477a3b
 
477a3b
 class ArgList {
477a3b
     WTF_MAKE_FAST_ALLOCATED;
477a3b
diff --git a/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp b/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp
477a3b
index e41a46dd57de..2ab3abb48117 100644
477a3b
--- a/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp
477a3b
+++ b/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp
477a3b
@@ -1,5 +1,5 @@
477a3b
 /*
477a3b
- * Copyright (C) 2020 Apple Inc. All rights reserved.
477a3b
+ * Copyright (C) 2020-2023 Apple Inc. All rights reserved.
477a3b
  *
477a3b
  * Redistribution and use in source and binary forms, with or without
477a3b
  * modification, are permitted provided that the following conditions
477a3b
@@ -220,7 +220,7 @@ AudioWorkletProcessor::AudioWorkletProcessor(AudioWorkletGlobalScope& globalScop
477a3b
     ASSERT(!isMainThread());
477a3b
 }
477a3b
 
477a3b
-void AudioWorkletProcessor::buildJSArguments(VM& vm, JSGlobalObject& globalObject, MarkedArgumentBufferBase& args, const Vector<RefPtr<AudioBus>>& inputs, Vector<Ref<AudioBus>>& outputs, const MemoryCompactLookupOnlyRobinHoodHashMap<String, std::unique_ptr<AudioFloatArray>>& paramValuesMap)
477a3b
+void AudioWorkletProcessor::buildJSArguments(VM& vm, JSGlobalObject& globalObject, MarkedArgumentBuffer& args, const Vector<RefPtr<AudioBus>>& inputs, Vector<Ref<AudioBus>>& outputs, const MemoryCompactLookupOnlyRobinHoodHashMap<String, std::unique_ptr<AudioFloatArray>>& paramValuesMap)
477a3b
 {
477a3b
     // For performance reasons, we cache the arrays passed to JS and reconstruct them only when the topology changes.
477a3b
     if (!copyDataFromBusesToJSArray(globalObject, inputs, toJSArray(m_jsInputs)))
477a3b
diff --git a/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h b/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h
477a3b
index 746059067f87..40751a2e501b 100644
477a3b
--- a/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h
477a3b
+++ b/Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h
477a3b
@@ -1,5 +1,5 @@
477a3b
 /*
477a3b
- * Copyright (C) 2020 Apple Inc. All rights reserved.
477a3b
+ * Copyright (C) 2020-2023 Apple Inc. All rights reserved.
477a3b
  *
477a3b
  * Redistribution and use in source and binary forms, with or without
477a3b
  * modification, are permitted provided that the following conditions
477a3b
@@ -41,7 +41,8 @@
477a3b
 
477a3b
 namespace JSC {
477a3b
 class JSArray;
477a3b
-class MarkedArgumentBufferBase;
477a3b
+template<typename T, size_t, class> class MarkedVector;
477a3b
+using MarkedArgumentBuffer = MarkedVector<JSValue, 8, RecordOverflow>;
477a3b
 }
477a3b
 
477a3b
 namespace WebCore {
477a3b
@@ -71,7 +72,7 @@ class AudioWorkletProcessor : public ScriptWrappable, public ThreadSafeRefCounte
477a3b
 
477a3b
 private:
477a3b
     explicit AudioWorkletProcessor(AudioWorkletGlobalScope&, const AudioWorkletProcessorConstructionData&);
477a3b
-    void buildJSArguments(JSC::VM&, JSC::JSGlobalObject&, JSC::MarkedArgumentBufferBase&, const Vector<RefPtr<AudioBus>>& inputs, Vector<Ref<AudioBus>>& outputs, const MemoryCompactLookupOnlyRobinHoodHashMap<String, std::unique_ptr<AudioFloatArray>>& paramValuesMap);
477a3b
+    void buildJSArguments(JSC::VM&, JSC::JSGlobalObject&, JSC::MarkedArgumentBuffer&, const Vector<RefPtr<AudioBus>>& inputs, Vector<Ref<AudioBus>>& outputs, const MemoryCompactLookupOnlyRobinHoodHashMap<String, std::unique_ptr<AudioFloatArray>>& paramValuesMap);
477a3b
 
477a3b
     AudioWorkletGlobalScope& m_globalScope;
477a3b
     String m_name;
477a3b
diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
477a3b
index ad135b5da8f8..a465d5a57a73 100644
477a3b
--- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp
477a3b
+++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
477a3b
@@ -573,6 +573,7 @@ static const unsigned StringDataIs8BitFlag = 0x80000000;
477a3b
 using DeserializationResult = std::pair<JSC::JSValue, SerializationReturnCode>;
477a3b
 
477a3b
 class CloneBase {
477a3b
+    WTF_FORBID_HEAP_ALLOCATION;
477a3b
 protected:
477a3b
     CloneBase(JSGlobalObject* lexicalGlobalObject)
477a3b
         : m_lexicalGlobalObject(lexicalGlobalObject)
477a3b
@@ -650,6 +651,7 @@ template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8
477a3b
 }
477a3b
 
477a3b
 class CloneSerializer : CloneBase {
477a3b
+    WTF_FORBID_HEAP_ALLOCATION;
477a3b
 public:
477a3b
     static SerializationReturnCode serialize(JSGlobalObject* lexicalGlobalObject, JSValue value, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, const Vector<RefPtr<ImageBitmap>>& imageBitmaps,
477a3b
 #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
477a3b
@@ -2318,6 +2320,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
477a3b
 }
477a3b
 
477a3b
 class CloneDeserializer : CloneBase {
477a3b
+    WTF_FORBID_HEAP_ALLOCATION;
477a3b
 public:
477a3b
     static String deserializeString(const Vector<uint8_t>& buffer)
477a3b
     {
477a3b
@@ -4285,10 +4288,10 @@ DeserializationResult CloneDeserializer::deserialize()
477a3b
 
477a3b
     Vector<uint32_t, 16> indexStack;
477a3b
     Vector<Identifier, 16> propertyNameStack;
477a3b
-    Vector<JSObject*, 32> outputObjectStack;
477a3b
-    Vector<JSValue, 4> mapKeyStack;
477a3b
-    Vector<JSMap*, 4> mapStack;
477a3b
-    Vector<JSSet*, 4> setStack;
477a3b
+    MarkedVector<JSObject*, 32> outputObjectStack;
477a3b
+    MarkedVector<JSValue, 4> mapKeyStack;
477a3b
+    MarkedVector<JSMap*, 4> mapStack;
477a3b
+    MarkedVector<JSSet*, 4> setStack;
477a3b
     Vector<WalkerState, 16> stateStack;
477a3b
     WalkerState lexicalGlobalObject = StateUnknown;
477a3b
     JSValue outValue;