Bug 1332602 - ArrayBufferObject::create should throw RangeError if the input is bigger than INT32_MAX. r=evilpie, a=jcristau
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 20 Jan 2017 18:23:33 +0100
changeset 366795 11a92eecc2bbd51957cc677087f1a5d4d5cdbba8
parent 366794 0862625a6d9d0d5ccf7e83a9c66403941eea3c6b
child 366796 e52e3bd70e084fd880c8c52fadfa91b06e7f1566
push id6852
push userryanvm@gmail.com
push dateTue, 31 Jan 2017 19:42:45 +0000
treeherdermozilla-beta@f271c045f7ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie, jcristau
bugs1332602
milestone52.0
Bug 1332602 - ArrayBufferObject::create should throw RangeError if the input is bigger than INT32_MAX. r=evilpie, a=jcristau
dom/base/FileReader.cpp
js/src/vm/ArrayBufferObject.cpp
--- a/dom/base/FileReader.cpp
+++ b/dom/base/FileReader.cpp
@@ -230,17 +230,18 @@ FileReader::DoOnLoadEnd(nsresult aStatus
     case FILE_AS_ARRAYBUFFER: {
       AutoJSAPI jsapi;
       if (!jsapi.Init(GetParentObject())) {
         FreeFileData();
         return NS_ERROR_FAILURE;
       }
 
       RootResultArrayBuffer();
-      mResultArrayBuffer = JS_NewArrayBufferWithContents(jsapi.cx(), mDataLen, mFileData);
+      mResultArrayBuffer =
+        JS_NewArrayBufferWithContents(jsapi.cx(), mDataLen, mFileData);
       if (!mResultArrayBuffer) {
         JS_ClearPendingException(jsapi.cx());
         rv = NS_ERROR_OUT_OF_MEMORY;
       } else {
         mFileData = nullptr; // Transfer ownership
       }
       break;
     }
@@ -406,22 +407,16 @@ FileReader::ReadFileContent(Blob& aBlob,
   MOZ_ASSERT(mAsyncStream);
 
   mTotal = mBlob->GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
-    // This limit comes from ArrayBufferObject::setByteLength.
-    if (mTotal > INT32_MAX) {
-      aRv.Throw(NS_ERROR_RANGE_ERR);
-      return;
-    }
-
     mFileData = js_pod_malloc<char>(mTotal);
     if (!mFileData) {
       NS_WARNING("Preallocation failed for ReadFileData");
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
   }
 
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1032,16 +1032,23 @@ ArrayBufferObject::setFlags(uint32_t fla
 ArrayBufferObject*
 ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents contents,
                           OwnsState ownsState /* = OwnsData */,
                           HandleObject proto /* = nullptr */,
                           NewObjectKind newKind /* = GenericObject */)
 {
     MOZ_ASSERT_IF(contents.kind() == MAPPED, contents);
 
+    // 24.1.1.1, step 3 (Inlined 6.2.6.1 CreateByteDataBlock, step 2).
+    // Refuse to allocate too large buffers, currently limited to ~2 GiB.
+    if (nbytes > INT32_MAX) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
+        return nullptr;
+    }
+
     // If we need to allocate data, try to use a larger object size class so
     // that the array buffer's data can be allocated inline with the object.
     // The extra space will be left unused by the object's fixed slots and
     // available for the buffer's data, see NewObject().
     size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&class_);
 
     size_t nslots = reservedSlots;
     bool allocated = false;