@@ -53,10 +53,17 @@ JSC::JSValue JSBufferList::concat(JSC::VM& vm, JSC::JSGlobalObject* lexicalGloba
5353 size_t i = 0 ;
5454 for (auto iter = m_deque.begin (); iter != m_deque.end (); ++iter) {
5555 auto array = JSC::jsDynamicCast<JSC::JSUint8Array*>(iter->get ());
56- if (!array)
57- continue ;
58- size_t length = array->byteLength ();
59- uint8Array->setFromTypedArray (lexicalGlobalObject, i, array, 0 , length, JSC::CopyType::Unobservable);
56+ if (UNLIKELY (!array)) {
57+ return throwTypeError (lexicalGlobalObject, throwScope, " concat can only be called when all buffers are Uint8Array" _s);
58+ }
59+ const size_t length = array->byteLength ();
60+ if (UNLIKELY (i + length > n)) {
61+ return throwRangeError (lexicalGlobalObject, throwScope, " specified size too small to fit all buffers" _s);
62+ }
63+ if (UNLIKELY (!uint8Array->setFromTypedArray (lexicalGlobalObject, i, array, 0 , length, JSC::CopyType::Unobservable))) {
64+ return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
65+ }
66+ i += length;
6067 }
6168
6269 RELEASE_AND_RETURN (throwScope, uint8Array);
@@ -68,16 +75,18 @@ JSC::JSValue JSBufferList::join(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalO
6875 if (length () == 0 ) {
6976 RELEASE_AND_RETURN (throwScope, JSC::jsEmptyString (vm));
7077 }
71- bool needSeq = false ;
78+ const bool needSeq = seq->length () != 0 ;
79+ const auto end = m_deque.end ();
7280 JSRopeString::RopeBuilder<RecordOverflow> ropeBuilder (vm);
73- for (auto iter = m_deque.begin (); iter != m_deque.end (); ++iter) {
74- auto str = JSC::jsCast<JSC::JSString*>(iter->get ());
81+ for (auto iter = m_deque.begin (); ;) {
82+ auto str = iter->get ().toString (lexicalGlobalObject);
83+ if (!ropeBuilder.append (str))
84+ return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
85+ if (++iter == end)
86+ break ;
7587 if (needSeq)
7688 if (!ropeBuilder.append (seq))
7789 return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
78- if (!ropeBuilder.append (str))
79- return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
80- needSeq = seq->length () != 0 ;
8190 }
8291 RELEASE_AND_RETURN (throwScope, ropeBuilder.release ());
8392}
@@ -142,11 +151,13 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG
142151 for (auto iter = m_deque.begin (); iter != m_deque.end () && n > 0 ; ++iter) {
143152 JSC::JSUint8Array* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(iter->get ());
144153 if (UNLIKELY (!array)) {
145- return throwOutOfMemoryError (lexicalGlobalObject, throwScope, " _getBuffer can only be called when all buffers are Uint8Array" _s);
154+ return throwTypeError (lexicalGlobalObject, throwScope, " _getBuffer can only be called when all buffers are Uint8Array" _s);
146155 }
147156 size_t length = array->byteLength ();
148157 if (length > n) {
149- uint8Array->setFromTypedArray (lexicalGlobalObject, offset, array, 0 , n, JSC::CopyType::Unobservable);
158+ if (UNLIKELY (!uint8Array->setFromTypedArray (lexicalGlobalObject, offset, array, 0 , n, JSC::CopyType::Unobservable))) {
159+ return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
160+ }
150161 // create a new array of size length - n.
151162 // is there a faster way to do this?
152163 auto arrayBuffer = JSC::ArrayBuffer::tryCreateUninitialized (length - n, 1 );
@@ -160,7 +171,9 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG
160171 memcpy (newArray->typedVector (), array->typedVector () + n, length - n);
161172 iter->set (vm, this , newArray);
162173 } else {
163- uint8Array->setFromTypedArray (lexicalGlobalObject, offset, array, 0 , length, JSC::CopyType::Unobservable);
174+ if (UNLIKELY (!uint8Array->setFromTypedArray (lexicalGlobalObject, offset, array, 0 , length, JSC::CopyType::Unobservable))) {
175+ return throwOutOfMemoryError (lexicalGlobalObject, throwScope);
176+ }
164177 m_deque.removeFirst ();
165178 }
166179 n -= static_cast <int32_t >(length);
0 commit comments