Throw the right exception upon memory exhaustion in Array::slice
https://bugs.webkit.org/show_bug.cgi?id=202650

Reviewed by Saam Barati.

JSTests:

* stress/array-slice-memory-exhaustion.js: Added.
(foo):

Source/JavaScriptCore:

Trivial change: just use tryCreate instead of create, and throw an exception if it fails.
No security implication: we were just crashing instead of throwing a catchable exception.

* runtime/ArrayBuffer.cpp:
(JSC::ArrayBuffer::slice const):
(JSC::ArrayBuffer::sliceImpl const):
* runtime/ArrayBuffer.h:
* runtime/JSArrayBufferPrototype.cpp:
(JSC::arrayBufferProtoFuncSlice):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251392 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog
index a443df1..581adf9 100644
--- a/JSTests/ChangeLog
+++ b/JSTests/ChangeLog
@@ -1,5 +1,15 @@
 2019-10-21  Robin Morisset  <rmorisset@apple.com>
 
+        Throw the right exception upon memory exhaustion in Array::slice
+        https://bugs.webkit.org/show_bug.cgi?id=202650
+
+        Reviewed by Saam Barati.
+
+        * stress/array-slice-memory-exhaustion.js: Added.
+        (foo):
+
+2019-10-21  Robin Morisset  <rmorisset@apple.com>
+
         Post increment/decrement should only call ToNumber once
         https://bugs.webkit.org/show_bug.cgi?id=202711
 
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 1c930b0..593058d 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,20 @@
+2019-10-21  Robin Morisset  <rmorisset@apple.com>
+
+        Throw the right exception upon memory exhaustion in Array::slice
+        https://bugs.webkit.org/show_bug.cgi?id=202650
+
+        Reviewed by Saam Barati.
+
+        Trivial change: just use tryCreate instead of create, and throw an exception if it fails.
+        No security implication: we were just crashing instead of throwing a catchable exception.
+
+        * runtime/ArrayBuffer.cpp:
+        (JSC::ArrayBuffer::slice const):
+        (JSC::ArrayBuffer::sliceImpl const):
+        * runtime/ArrayBuffer.h:
+        * runtime/JSArrayBufferPrototype.cpp:
+        (JSC::arrayBufferProtoFuncSlice):
+
 2019-10-21  Basuke Suzuki  <Basuke.Suzuki@sony.com>
 
         [WinCairo][PlayStation] Add automation support for RemoteInspector SocketServer implementation.
diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.cpp b/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
index 671bdb7..07bda38 100644
--- a/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
@@ -295,21 +295,22 @@
     return clampValue(index, 0, currentLength);
 }
 
-Ref<ArrayBuffer> ArrayBuffer::slice(double begin, double end) const
+RefPtr<ArrayBuffer> ArrayBuffer::slice(double begin, double end) const
 {
     return sliceImpl(clampIndex(begin), clampIndex(end));
 }
 
-Ref<ArrayBuffer> ArrayBuffer::slice(double begin) const
+RefPtr<ArrayBuffer> ArrayBuffer::slice(double begin) const
 {
     return sliceImpl(clampIndex(begin), byteLength());
 }
 
-Ref<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
+RefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
 {
     unsigned size = begin <= end ? end - begin : 0;
-    auto result = ArrayBuffer::create(static_cast<const char*>(data()) + begin, size);
-    result->setSharingMode(sharingMode());
+    auto result = ArrayBuffer::tryCreate(static_cast<const char*>(data()) + begin, size);
+    if (result)
+        result->setSharingMode(sharingMode());
     return result;
 }
 
diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.h b/Source/JavaScriptCore/runtime/ArrayBuffer.h
index 7c05bbc..e6f55ce 100644
--- a/Source/JavaScriptCore/runtime/ArrayBuffer.h
+++ b/Source/JavaScriptCore/runtime/ArrayBuffer.h
@@ -132,8 +132,8 @@
 
     inline size_t gcSizeEstimateInBytes() const;
 
-    JS_EXPORT_PRIVATE Ref<ArrayBuffer> slice(double begin, double end) const;
-    JS_EXPORT_PRIVATE Ref<ArrayBuffer> slice(double begin) const;
+    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin, double end) const;
+    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin) const;
     
     inline void pin();
     inline void unpin();
@@ -158,7 +158,7 @@
     static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned);
     static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
     ArrayBuffer(ArrayBufferContents&&);
-    Ref<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
+    RefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
     inline unsigned clampIndex(double index) const;
     static inline unsigned clampValue(double x, unsigned left, unsigned right);
 
diff --git a/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp b/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp
index b110160..1fea743 100644
--- a/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp
@@ -55,6 +55,8 @@
         end = thisObject->impl()->byteLength();
     
     auto newBuffer = thisObject->impl()->slice(begin, end);
+    if (!newBuffer)
+        return JSValue::encode(throwOutOfMemoryError(callFrame, scope));
     
     Structure* structure = globalObject->arrayBufferStructure(newBuffer->sharingMode());
     
diff --git a/Source/WebCore/platform/mock/mediasource/MockBox.cpp b/Source/WebCore/platform/mock/mediasource/MockBox.cpp
index 7ad7084..7cb2328 100644
--- a/Source/WebCore/platform/mock/mediasource/MockBox.cpp
+++ b/Source/WebCore/platform/mock/mediasource/MockBox.cpp
@@ -98,10 +98,10 @@
 
     while (offset < m_length) {
         auto subBuffer = data->slice(offset);
-        if (MockBox::peekType(subBuffer.ptr()) != MockTrackBox::type())
+        if (MockBox::peekType(subBuffer.get()) != MockTrackBox::type())
             break;
 
-        MockTrackBox trackBox(subBuffer.ptr());
+        MockTrackBox trackBox(subBuffer.get());
         offset += trackBox.length();
         m_tracks.append(trackBox);
     }