Bug 1265076 - make ArrayBufferInputStream obey readSegments contract; r?mcmanus draft
authorTom Tromey <tom@tromey.com>
Fri, 15 Apr 2016 14:43:14 -0600
changeset 352167 cfc499f804e973d90ad32a4897d2c2c91cca936e
parent 352011 0260dd297a25b97b11dfa208c3d556cb7b62542c
child 518597 93bf49c7e5ad648318ecbded2a04ce0f695ae5ff
push id15635
push userbmo:ttromey@mozilla.com
push dateFri, 15 Apr 2016 20:45:38 +0000
reviewersmcmanus
bugs1265076
milestone48.0a1
Bug 1265076 - make ArrayBufferInputStream obey readSegments contract; r?mcmanus MozReview-Commit-ID: 7RSzey2vdPL
netwerk/base/ArrayBufferInputStream.cpp
netwerk/test/mochitests/test_arraybufferinputstream.html
--- a/netwerk/base/ArrayBufferInputStream.cpp
+++ b/netwerk/base/ArrayBufferInputStream.cpp
@@ -87,16 +87,18 @@ ArrayBufferInputStream::ReadSegments(nsW
     uint32_t remaining = mBufferLength - mPos;
     MOZ_ASSERT(mArrayBuffer);
     uint32_t byteLength = JS_GetArrayBufferByteLength(mArrayBuffer->get());
     if (byteLength == 0) {
       mClosed = true;
       return NS_BASE_STREAM_CLOSED;
     }
 
+    // If you change the size of this buffer, please also remember to
+    // update test_arraybufferinputstream.html.
     char buffer[8192];
     uint32_t count = std::min(std::min(aCount, remaining), uint32_t(mozilla::ArrayLength(buffer)));
     if (count == 0) {
       break;
     }
 
     // It is just barely possible that writer() will detach the ArrayBuffer's
     // data, setting its length to zero. Or move the data to a different memory
@@ -106,17 +108,17 @@ ArrayBufferInputStream::ReadSegments(nsW
     {
       JS::AutoCheckCannotGC nogc;
       bool isShared;
       char* src = (char*) JS_GetArrayBufferData(mArrayBuffer->get(), &isShared, nogc) + mOffset + mPos;
       MOZ_ASSERT(!isShared);    // Because ArrayBuffer
       memcpy(buffer, src, count);
     }
     uint32_t written;
-    nsresult rv = writer(this, closure, buffer, 0, count, &written);
+    nsresult rv = writer(this, closure, buffer, *result, count, &written);
     if (NS_FAILED(rv)) {
       // InputStreams do not propagate errors to caller.
       return NS_OK;
     }
 
     NS_ASSERTION(written <= count,
                  "writer should not write more than we asked it to write");
     mPos += written;
--- a/netwerk/test/mochitests/test_arraybufferinputstream.html
+++ b/netwerk/test/mochitests/test_arraybufferinputstream.html
@@ -44,16 +44,43 @@ function test()
     sis.read(1);
     ok(false, "reading from stream shouldn't have worked");
   }
   catch (e)
   {
     ok(e.result === Cr.NS_BASE_STREAM_CLOSED,
        "detaching underneath an input stream should close it");
   }
+
+  // A regression test for bug 1265076.  Previously, overflowing
+  // the internal buffer from readSegments would cause incorrect
+  // copying.  The constant mirrors the value in
+  // ArrayBufferInputStream::readSegments.
+  var size = 8192;
+  ab = new ArrayBuffer(2 * size);
+  ta = new Uint8Array(ab);
+
+  var i;
+  for (i = 0; i < size; ++i) {
+    ta[i] = 'x'.charCodeAt(0);
+  }
+  for (i = 0; i < size; ++i) {
+    ta[size + i] = 'y'.charCodeAt(0);
+  }
+
+  abis = Cc["@mozilla.org/io/arraybuffer-input-stream;1"]
+           .createInstance(Ci.nsIArrayBufferInputStream);
+  abis.setData(ab, 0, 2 * size);
+
+  sis = Cc["@mozilla.org/scriptableinputstream;1"]
+          .createInstance(Ci.nsIScriptableInputStream);
+  sis.init(abis);
+
+  var result = sis.read(2 * size);
+  is(result, "x".repeat(size) + "y".repeat(size), "correctly read the data");
 }
 
 test();
 </script>
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none"></div>