Skip to content

Commit 85a5e5a

Browse files
net: fix bytesWritten during writev
When a writev is caused on a socket (sometimes through corking and uncorking), previously net would call Buffer.byteLength on the array of buffers and chunks. This throws a TypeError, because Buffer.byteLength throws when passed a non-string. In dbfe8c4, behavior changed to throw when passed a non-string. This is correct behavior. Previously, it would cast the argument to a string, so before this commit, bytesWritten would give an erroneous value. This commit corrects the behavior equally both before and after dbfe8c4. This commit fixes this bug by iterating over each chunk in the pending stack and calculating the length individually. Also adds a regression test. This additionally changes an `instanceof Buffer` check to `typeof !== 'string'`, which should be equivalent. PR-URL: #14236 Reviewed-By: Brian White <mscdex@mscdex.net> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Refs: #2960
1 parent 75bf8a9 commit 85a5e5a

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

lib/net.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,19 @@ protoGetter('bytesWritten', function bytesWritten() {
827827
bytes += Buffer.byteLength(el.chunk, el.encoding);
828828
});
829829

830-
if (data) {
831-
if (data instanceof Buffer)
830+
if (Array.isArray(data)) {
831+
// was a writev, iterate over chunks to get total length
832+
for (var i = 0; i < data.length; i++) {
833+
const chunk = data[i];
834+
835+
if (data.allBuffers || chunk instanceof Buffer)
836+
bytes += chunk.length;
837+
else
838+
bytes += Buffer.byteLength(chunk.chunk, chunk.encoding);
839+
}
840+
} else if (data) {
841+
// Writes are either a string or a Buffer.
842+
if (typeof data !== 'string')
832843
bytes += data.length;
833844
else
834845
bytes += Buffer.byteLength(data, encoding);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const net = require('net');
6+
7+
const server = net.createServer(function(socket) {
8+
socket.end();
9+
});
10+
11+
server.listen(0, common.mustCall(function() {
12+
const socket = net.connect(server.address().port);
13+
14+
// Cork the socket, then write twice; this should cause a writev, which
15+
// previously caused an err in the bytesWritten count.
16+
socket.cork();
17+
18+
socket.write('one');
19+
socket.write(new Buffer('twø', 'utf8'));
20+
21+
socket.uncork();
22+
23+
// one = 3 bytes, twø = 4 bytes
24+
assert.strictEqual(socket.bytesWritten, 3 + 4);
25+
26+
socket.on('connect', common.mustCall(function() {
27+
assert.strictEqual(socket.bytesWritten, 3 + 4);
28+
}));
29+
30+
socket.on('end', common.mustCall(function() {
31+
assert.strictEqual(socket.bytesWritten, 3 + 4);
32+
33+
server.close();
34+
}));
35+
}));

0 commit comments

Comments
 (0)