Blame SOURCES/CVE-2023-28205.patch

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