Skip to content

Commit f31d47e

Browse files
mcollinamarco-ippolito
authored andcommittedFeb 12, 2024
zlib: pause stream if outgoing buffer is full
Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: nodejs-private/node-private#540 Reviewed-By: Robert Nagy <ronagy@icloud.com> Ref: https://hackerone.com/reports/2284065 PR-URL: nodejs-private/node-private#542 CVE-ID: CVE-2024-22025
1 parent f48b896 commit f31d47e

File tree

3 files changed

+62
-17
lines changed

3 files changed

+62
-17
lines changed
 

‎lib/zlib.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,11 @@ function processCallback() {
560560
self.bytesWritten += inDelta;
561561

562562
const have = handle.availOutBefore - availOutAfter;
563+
let streamBufferIsFull = false;
563564
if (have > 0) {
564565
const out = self._outBuffer.slice(self._outOffset, self._outOffset + have);
565566
self._outOffset += have;
566-
self.push(out);
567+
streamBufferIsFull = !self.push(out);
567568
} else {
568569
assert(have === 0, 'have should not go down');
569570
}
@@ -588,13 +589,29 @@ function processCallback() {
588589
handle.inOff += inDelta;
589590
handle.availInBefore = availInAfter;
590591

591-
this.write(handle.flushFlag,
592-
this.buffer, // in
593-
handle.inOff, // in_off
594-
handle.availInBefore, // in_len
595-
self._outBuffer, // out
596-
self._outOffset, // out_off
597-
self._chunkSize); // out_len
592+
593+
if (!streamBufferIsFull) {
594+
this.write(handle.flushFlag,
595+
this.buffer, // in
596+
handle.inOff, // in_off
597+
handle.availInBefore, // in_len
598+
self._outBuffer, // out
599+
self._outOffset, // out_off
600+
self._chunkSize); // out_len
601+
} else {
602+
const oldRead = self._read;
603+
self._read = (n) => {
604+
self._read = oldRead;
605+
this.write(handle.flushFlag,
606+
this.buffer, // in
607+
handle.inOff, // in_off
608+
handle.availInBefore, // in_len
609+
self._outBuffer, // out
610+
self._outOffset, // out_off
611+
self._chunkSize); // out_len
612+
self._read(n);
613+
};
614+
}
598615
return;
599616
}
600617

‎test/parallel/test-zlib-brotli-16GB.js

+22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/parallel/test-zlib-params.js

+15-9
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,29 @@ const deflater = zlib.createDeflate(opts);
1212
const chunk1 = file.slice(0, chunkSize);
1313
const chunk2 = file.slice(chunkSize);
1414
const blkhdr = Buffer.from([0x00, 0x5a, 0x82, 0xa5, 0x7d]);
15-
const expected = Buffer.concat([blkhdr, chunk2]);
16-
let actual;
15+
const blkftr = Buffer.from('010000ffff7dac3072', 'hex');
16+
const expected = Buffer.concat([blkhdr, chunk2, blkftr]);
17+
const bufs = [];
18+
19+
function read() {
20+
let buf;
21+
while ((buf = deflater.read()) !== null) {
22+
bufs.push(buf);
23+
}
24+
}
1725

1826
deflater.write(chunk1, function() {
1927
deflater.params(0, zlib.constants.Z_DEFAULT_STRATEGY, function() {
2028
while (deflater.read());
21-
deflater.end(chunk2, function() {
22-
const bufs = [];
23-
let buf;
24-
while ((buf = deflater.read()) !== null)
25-
bufs.push(buf);
26-
actual = Buffer.concat(bufs);
27-
});
29+
30+
deflater.on('readable', read);
31+
32+
deflater.end(chunk2);
2833
});
2934
while (deflater.read());
3035
});
3136

3237
process.once('exit', function() {
38+
const actual = Buffer.concat(bufs);
3339
assert.deepStrictEqual(actual, expected);
3440
});

0 commit comments

Comments
 (0)
Please sign in to comment.