mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
zlib: pause stream if outgoing buffer is full
Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: https://github.com/nodejs-private/node-private/pull/540 Reviewed-By: Robert Nagy <ronagy@icloud.com> Ref: https://hackerone.com/reports/2284065 CVE-ID: CVE-2024-22025
This commit is contained in:
1 parent
6d14352c51
commit
9052ef43dc
3 files changed
+62
-17
No files matched your search
+25
-8
@@ -560,10 +560,11 @@ function processCallback() {
|
||||
self.bytesWritten += inDelta;
|
||||
|
||||
const have = handle.availOutBefore - availOutAfter;
|
||||
let streamBufferIsFull = false;
|
||||
if (have > 0) {
|
||||
const out = self._outBuffer.slice(self._outOffset, self._outOffset + have);
|
||||
self._outOffset += have;
|
||||
self.push(out);
|
||||
streamBufferIsFull = !self.push(out);
|
||||
} else {
|
||||
assert(have === 0, 'have should not go down');
|
||||
}
|
||||
@@ -588,13 +589,29 @@ function processCallback() {
|
||||
handle.inOff += inDelta;
|
||||
handle.availInBefore = availInAfter;
|
||||
|
||||
this.write(handle.flushFlag,
|
||||
this.buffer, // in
|
||||
handle.inOff, // in_off
|
||||
handle.availInBefore, // in_len
|
||||
self._outBuffer, // out
|
||||
self._outOffset, // out_off
|
||||
self._chunkSize); // out_len
|
||||
|
||||
if (!streamBufferIsFull) {
|
||||
this.write(handle.flushFlag,
|
||||
this.buffer, // in
|
||||
handle.inOff, // in_off
|
||||
handle.availInBefore, // in_len
|
||||
self._outBuffer, // out
|
||||
self._outOffset, // out_off
|
||||
self._chunkSize); // out_len
|
||||
} else {
|
||||
const oldRead = self._read;
|
||||
self._read = (n) => {
|
||||
self._read = oldRead;
|
||||
this.write(handle.flushFlag,
|
||||
this.buffer, // in
|
||||
handle.inOff, // in_off
|
||||
handle.availInBefore, // in_len
|
||||
self._outBuffer, // out
|
||||
self._outOffset, // out_off
|
||||
self._chunkSize); // out_len
|
||||
self._read(n);
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const { createBrotliDecompress } = require('node:zlib');
|
||||
const strictEqual = require('node:assert').strictEqual;
|
||||
|
||||
// This tiny HEX string is a 16GB file.
|
||||
// This test verifies that the stream actually stops.
|
||||
/* eslint-disable max-len */
|
||||
const content = 'cfffff7ff82700e2b14020f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c32200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600Line truncated
|
||||
|
||||
const buf = Buffer.from(content, 'hex');
|
||||
|
||||
const decoder = createBrotliDecompress();
|
||||
decoder.end(buf);
|
||||
|
||||
// We need to wait to verify that the libuv thread pool had time
|
||||
// to process the data and the buffer is not empty.
|
||||
setTimeout(common.mustCall(() => {
|
||||
// There is only one chunk in the buffer
|
||||
strictEqual(decoder._readableState.buffer.length, 1);
|
||||
}), common.platformTimeout(100));
|
||||
@@ -12,23 +12,29 @@ const deflater = zlib.createDeflate(opts);
|
||||
const chunk1 = file.slice(0, chunkSize);
|
||||
const chunk2 = file.slice(chunkSize);
|
||||
const blkhdr = Buffer.from([0x00, 0x5a, 0x82, 0xa5, 0x7d]);
|
||||
const expected = Buffer.concat([blkhdr, chunk2]);
|
||||
let actual;
|
||||
const blkftr = Buffer.from('010000ffff7dac3072', 'hex');
|
||||
const expected = Buffer.concat([blkhdr, chunk2, blkftr]);
|
||||
const bufs = [];
|
||||
|
||||
function read() {
|
||||
let buf;
|
||||
while ((buf = deflater.read()) !== null) {
|
||||
bufs.push(buf);
|
||||
}
|
||||
}
|
||||
|
||||
deflater.write(chunk1, function() {
|
||||
deflater.params(0, zlib.constants.Z_DEFAULT_STRATEGY, function() {
|
||||
while (deflater.read());
|
||||
deflater.end(chunk2, function() {
|
||||
const bufs = [];
|
||||
let buf;
|
||||
while ((buf = deflater.read()) !== null)
|
||||
bufs.push(buf);
|
||||
actual = Buffer.concat(bufs);
|
||||
});
|
||||
|
||||
deflater.on('readable', read);
|
||||
|
||||
deflater.end(chunk2);
|
||||
});
|
||||
while (deflater.read());
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
const actual = Buffer.concat(bufs);
|
||||
assert.deepStrictEqual(actual, expected);
|
||||
});
|
||||
Reference in new issue
Block a user