Bug 863770 - Pass in an ArrayBuffer object for nsBinaryInputStream::ReadAsArrayBuffer to use, for cases when the compartment in which it resides matters. r=vlad
authorJosh Matthews <josh@joshmatthews.net>
Mon, 22 Apr 2013 23:33:55 +0200
changeset 129467 a991d0f4469bc71103f9409090973e43c5483566
parent 129466 19510f91504bd696498f027aae7255e4b7e905ed
child 129468 f59811fe0fb3d303fd20abc4e10432488c3d3db5
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs863770
milestone23.0a1
Bug 863770 - Pass in an ArrayBuffer object for nsBinaryInputStream::ReadAsArrayBuffer to use, for cases when the compartment in which it resides matters. r=vlad
dom/network/src/TCPSocket.js
xpcom/io/nsBinaryStream.cpp
xpcom/io/nsIBinaryInputStream.idl
--- a/dom/network/src/TCPSocket.js
+++ b/dom/network/src/TCPSocket.js
@@ -558,17 +558,19 @@ TCPSocket.prototype = {
     }
 
     this.callListener("close");
   },
 
   // nsIStreamListener (Triggered by _inputStreamPump.asyncRead)
   onDataAvailable: function ts_onDataAvailable(request, context, inputStream, offset, count) {
     if (this._binaryType === "arraybuffer") {
-      this.callListener("data", this._inputStreamBinary.readArrayBuffer(count));
+      let buffer = new (this.useWin ? this.useWin.ArrayBuffer : ArrayBuffer)(count);
+      this._inputStreamBinary.readArrayBuffer(count, buffer);
+      this.callListener("data", buffer);
     } else {
       this.callListener("data", this._inputStreamScriptable.read(count));
     }
   },
 
   classID: Components.ID("{cda91b22-6472-11e1-aa11-834fec09cd0a}"),
 
   classInfo: XPCOMUtils.generateCI({
--- a/xpcom/io/nsBinaryStream.cpp
+++ b/xpcom/io/nsBinaryStream.cpp
@@ -714,36 +714,38 @@ nsBinaryInputStream::ReadBytes(uint32_t 
 
 NS_IMETHODIMP
 nsBinaryInputStream::ReadByteArray(uint32_t aLength, uint8_t* *_rval)
 {
     return ReadBytes(aLength, reinterpret_cast<char **>(_rval));
 }
 
 NS_IMETHODIMP
-nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength, JSContext* cx, JS::Value* _rval)
+nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength, const JS::Value& aBuffer, JSContext* cx)
 {
     JSAutoRequest ar(cx);
-    JS::RootedObject buffer(cx, JS_NewArrayBuffer(cx, aLength));
-    if (!buffer) {
+    if (!aBuffer.isObject()) {
         return NS_ERROR_FAILURE;
     }
-    uint8_t* data = JS_GetArrayBufferData(buffer);
+    JS::RootedObject buffer(cx, &aBuffer.toObject());
+    if (!JS_IsArrayBufferObject(buffer) ||
+        JS_GetArrayBufferByteLength(buffer) < aLength) {
+        return NS_ERROR_FAILURE;
+    }
+    uint8_t* data = JS_GetArrayBufferData(&aBuffer.toObject());
     if (!data) {
         return NS_ERROR_FAILURE;
     }
 
     uint32_t bytesRead;
     nsresult rv = Read(reinterpret_cast<char*>(data), aLength, &bytesRead);
     NS_ENSURE_SUCCESS(rv, rv);
     if (bytesRead != aLength) {
         return NS_ERROR_FAILURE;
     }
-
-    *_rval = JS::ObjectValue(*buffer);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBinaryInputStream::ReadObject(bool aIsStrongRef, nsISupports* *aObject)
 {
     nsCID cid;
     nsIID iid;
--- a/xpcom/io/nsIBinaryInputStream.idl
+++ b/xpcom/io/nsIBinaryInputStream.idl
@@ -68,21 +68,24 @@ interface nsIBinaryInputStream : nsIInpu
      */
     void readByteArray(in uint32_t aLength,
                        [array, size_is(aLength), retval] out uint8_t aBytes);
 
     /**
      * Read opaque bytes from the stream, storing the results in an ArrayBuffer.
      *
      * @param aLength the number of bytes that must be read
+     * @param aArrayBuffer the arraybuffer in which to store the results
+     * Note: passing view.buffer, where view is an ArrayBufferView of an
+     *       ArrayBuffer, is not valid unless view.byteOffset == 0.
      *
      * @throws NS_ERROR_FAILURE if it can't read aLength bytes
      */
     [implicit_jscontext]
-    jsval readArrayBuffer(in uint32_t aLength);
+    void readArrayBuffer(in uint32_t aLength, in jsval aArrayBuffer);
 };
 
 %{C++
 
 #ifdef MOZILLA_INTERNAL_API
 #include "nsString.h"
 
 inline nsresult