Bug 1265076 - make ArrayBufferInputStream obey readSegments contract; r?mcmanus
MozReview-Commit-ID: 7RSzey2vdPL
--- 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>