summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruki00a <uki00a@gmail.com>2020-05-20 23:34:20 +0900
committerGitHub <noreply@github.com>2020-05-20 16:34:20 +0200
commit9b4da88a96ce4c793e7b15d9b340fa6326a29a82 (patch)
treec1749398932a769be55022e83b50002d40702c5b
parentef14d62462d7f5bc2f091c3521409b4a16c5f87c (diff)
fix(std/io): BufReader should not share the internal buffer across reads (#4543)
-rw-r--r--std/io/bufio.ts6
-rw-r--r--std/io/bufio_test.ts20
-rw-r--r--std/textproto/test.ts13
3 files changed, 38 insertions, 1 deletions
diff --git a/std/io/bufio.ts b/std/io/bufio.ts
index aa74809fe..5c005672a 100644
--- a/std/io/bufio.ts
+++ b/std/io/bufio.ts
@@ -338,7 +338,11 @@ export class BufReader implements Reader {
// Buffer full?
if (this.buffered() >= this.buf.byteLength) {
this.r = this.w;
- throw new BufferFullError(this.buf);
+ // #4521 The internal buffer should not be reused across reads because it causes corruption of data.
+ const oldbuf = this.buf;
+ const newbuf = this.buf.slice(0);
+ this.buf = newbuf;
+ throw new BufferFullError(oldbuf);
}
s = this.w - this.r; // do not rescan area we scanned before
diff --git a/std/io/bufio_test.ts b/std/io/bufio_test.ts
index c49023814..d3e39bff6 100644
--- a/std/io/bufio_test.ts
+++ b/std/io/bufio_test.ts
@@ -12,6 +12,7 @@ import {
BufWriterSync,
BufferFullError,
PartialReadError,
+ ReadLineResult,
readStringDelim,
readLines,
} from "./bufio.ts";
@@ -445,3 +446,22 @@ Deno.test("readStringDelimAndLines", async function (): Promise<void> {
assertEquals(lines_.length, 10);
assertEquals(lines_, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
});
+
+Deno.test(async function bufReaderShouldNotShareArrayBufferAcrossReads() {
+ const decoder = new TextDecoder();
+ const data = "abcdefghijklmnopqrstuvwxyz";
+ const bufSize = 25;
+ const b = new BufReader(stringsReader(data), bufSize);
+
+ const r1 = (await b.readLine()) as ReadLineResult;
+ assertNotEOF(r1);
+ assertEquals(decoder.decode(r1.line), "abcdefghijklmnopqrstuvwxy");
+
+ const r2 = (await b.readLine()) as ReadLineResult;
+ assertNotEOF(r2);
+ assertEquals(decoder.decode(r2.line), "z");
+ assert(
+ r1.line.buffer !== r2.line.buffer,
+ "array buffer should not be shared across reads"
+ );
+});
diff --git a/std/textproto/test.ts b/std/textproto/test.ts
index 3b71bc08c..ec66bfd8c 100644
--- a/std/textproto/test.ts
+++ b/std/textproto/test.ts
@@ -180,3 +180,16 @@ test({
assertEquals(m.get("Content-Disposition"), 'form-data; name="test"');
},
});
+
+test({
+ name: "[textproto] #4521 issue",
+ async fn() {
+ const input = "abcdefghijklmnopqrstuvwxyz";
+ const bufSize = 25;
+ const tp = new TextProtoReader(
+ new BufReader(stringsReader(input), bufSize)
+ );
+ const line = await tp.readLine();
+ assertEquals(line, input);
+ },
+});