Repository navigation
Memory leak when using zlib.inflate to inflate invalid data v10.9.0 #22705
Description
Version: 10.9.0
Platform: Linux Ubuntu 3.13.0-36-generic
Subsystem: zlib
I've recently updated a large project from Node 8.11.3 to 10.9.0 but the service crashes after a few minutes because of memory exhaustion (4GB RAM). I've narrowed down the issue to the use of the asynchronous zlib.inflate method if the input isn't a valid input.
I've been able to create a small script which shows the issue
const crypto = require('crypto'), zlib = require('zlib');
const LOOPS = 10 * 1000;
let body = process.argv[2] === "valid" ? zlib.deflateSync(crypto.randomBytes(1024)) :
crypto.randomBytes(1024);
let totalRuns = 0;
let initialRSS = process.memoryUsage().rss;
setInterval(() => {
for (let i = 0; i < LOOPS; i++) {
zlib.inflate(body, (error, result) => { });
}
totalRuns += LOOPS
let currentRSS = process.memoryUsage().rss;
console.log(totalRuns, currentRSS, currentRSS - initialRSS);
}, 100);
When using Node 8.11.3 I get the following output from that script, you can see memory usage levels out around 280MiB.
Loops ** Current RSS** RSS Increase
10000 150556672 132362240
100000 281853952 263659520
200000 294563840 276369408
1000000 297381888 279158784
Switching to Node 10.9.0 I get the following output
Loops ** Current RSS** RSS Increase
10000 149655552 130969600
100000 790159360 771473408
200000 1477070848 1458384896
After 200k iterations the 8.11.3 version uses 280MiB but the 10.9.0 version is using 1400MiB of memory. After about 300k iterations using 10.9.0 the process crashes because it runs out of RAM.
Running the script with the "valid" parameter to send zlib a valid stream shows an increase in memory but it's small and eventually levels out and doesn't run out of memory.
node memoryleak.js valid
10000 156794880 137863168
100000 505155584 486223872
200000 546017280 527085568
I've corrected our service so that we check for invalid streams before trying to inflate them but I thought that there is potential for a denial of service against any service which uses zlib.inflate to decompress user input.
Activity
zlib: fix memory leak for invalid input
addaleax commentedon Sep 5, 2018
Fix is in #22713 :)
zlib: fix memory leak for invalid input
laino commentedon Sep 7, 2018
This might not just affect invalid data. When using the 'ws' module with per message deflate enabled, my application quickly reaches 3GB memory usage. Without it uses about 800MB.
I only managed to grab one heapdump so far before my server inevitably runs out of memory. Zlib internals looked like a major culprit.
Here's what I'm looking at on Node v10.9.0: https://i.imgur.com/byTUInU.png
I'm not too good at reading these, but this really looks like zlib being the culprit to me.
If this is a separate issue I'll open a ticket.
Edit: Nevermind, I somehow missed the fact that this ticket was about inflate, not deflate.
zlib: fix memory leak for invalid input