Bug 1265076 - make ArrayBufferInputStream obey readSegments contract; r=mcmanus
authorTom Tromey <tom@tromey.com>
Fri, 15 Apr 2016 14:43:14 -0600
changeset 331846 a2a9cec0506a8646416afcdf1f46ac46ffa97bc4
parent 331845 2a393602414ef52b6104f61fe7d5182d2b3d638e
child 331847 242336dca06d789d466a2ac7700405c02e7ba487
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcmanus
bugs1265076
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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>