Skip to content

Commit 9f1b790

Browse files
addaleaxMylesBorins
authored andcommitted
net: make holding the buffer in memory more robust
Set the `req.buffer` property, which serves as a way of keeping a `Buffer` alive that is being written to a stream, on the C++ side instead of the JS side. This closes a hole where buffers that were temporarily created in order to write strings with uncommon encodings (e.g. `hex`) were passed to the native side without being set as `req.buffer`. Fixes: #8251 PR-URL: #8252 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent d1a50b3 commit 9f1b790

4 files changed

+67
-1
lines changed

lib/net.js

-1
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,6 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
685685
} else {
686686
var enc;
687687
if (data instanceof Buffer) {
688-
req.buffer = data; // Keep reference alive.
689688
enc = 'buffer';
690689
} else {
691690
enc = encoding;

src/stream_base.cc

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
225225

226226
err = DoWrite(req_wrap, bufs, count, nullptr);
227227
req_wrap_obj->Set(env->async(), True(env->isolate()));
228+
req_wrap_obj->Set(env->buffer_string(), args[1]);
228229

229230
if (err)
230231
req_wrap->Dispose();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
// Flags: --expose-gc
3+
4+
// Note: This is a variant of test-net-write-fully-async-hex-string.js.
5+
// This always worked, but it seemed appropriate to add a test that checks the
6+
// behaviour for Buffers, too.
7+
const common = require('../common');
8+
const net = require('net');
9+
10+
const data = Buffer.alloc(1000000);
11+
12+
const server = net.createServer(common.mustCall(function(conn) {
13+
conn.resume();
14+
})).listen(0, common.mustCall(function() {
15+
const conn = net.createConnection(this.address().port, common.mustCall(() => {
16+
let count = 0;
17+
18+
function writeLoop() {
19+
if (count++ === 200) {
20+
conn.destroy();
21+
server.close();
22+
return;
23+
}
24+
25+
while (conn.write(Buffer.from(data)));
26+
global.gc(true);
27+
// The buffer allocated above should still be alive.
28+
}
29+
30+
conn.on('drain', writeLoop);
31+
32+
writeLoop();
33+
}));
34+
}));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
// Flags: --expose-gc
3+
4+
// Regression test for https://github.com/nodejs/node/issues/8251.
5+
const common = require('../common');
6+
const net = require('net');
7+
8+
const data = Buffer.alloc(1000000).toString('hex');
9+
10+
const server = net.createServer(common.mustCall(function(conn) {
11+
conn.resume();
12+
})).listen(0, common.mustCall(function() {
13+
const conn = net.createConnection(this.address().port, common.mustCall(() => {
14+
let count = 0;
15+
16+
function writeLoop() {
17+
if (count++ === 20) {
18+
conn.destroy();
19+
server.close();
20+
return;
21+
}
22+
23+
while (conn.write(data, 'hex'));
24+
global.gc(true);
25+
// The buffer allocated inside the .write() call should still be alive.
26+
}
27+
28+
conn.on('drain', writeLoop);
29+
30+
writeLoop();
31+
}));
32+
}));

0 commit comments

Comments
 (0)