child_process: add safety checks on stdio access

When a child process is spawned, there is no guarantee that stdout
and stderr will be created successfully. This commit adds checks
before attempting to access the streams.

PR-URL: https://github.com/nodejs/node/pull/3799
Reviewed-By: Brian White <mscdex@mscdex.net>
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
cjihrig 2015-11-12 14:30:20 -05:00 committed by James M Snell
parent f8390fdd75
commit 7b355c5bb3

View File

@ -222,14 +222,22 @@ exports.execFile = function(file /*, args, options, callback*/) {
function errorhandler(e) { function errorhandler(e) {
ex = e; ex = e;
child.stdout.destroy();
child.stderr.destroy(); if (child.stdout)
child.stdout.destroy();
if (child.stderr)
child.stderr.destroy();
exithandler(); exithandler();
} }
function kill() { function kill() {
child.stdout.destroy(); if (child.stdout)
child.stderr.destroy(); child.stdout.destroy();
if (child.stderr)
child.stderr.destroy();
killed = true; killed = true;
try { try {
@ -247,37 +255,42 @@ exports.execFile = function(file /*, args, options, callback*/) {
}, options.timeout); }, options.timeout);
} }
child.stdout.addListener('data', function(chunk) { if (child.stdout) {
stdoutLen += chunk.length; if (encoding)
child.stdout.setEncoding(encoding);
if (stdoutLen > options.maxBuffer) { child.stdout.addListener('data', function(chunk) {
ex = new Error('stdout maxBuffer exceeded'); stdoutLen += chunk.length;
kill();
} else {
if (!encoding)
_stdout.push(chunk);
else
_stdout += chunk;
}
});
child.stderr.addListener('data', function(chunk) { if (stdoutLen > options.maxBuffer) {
stderrLen += chunk.length; ex = new Error('stdout maxBuffer exceeded');
kill();
} else {
if (!encoding)
_stdout.push(chunk);
else
_stdout += chunk;
}
});
}
if (stderrLen > options.maxBuffer) { if (child.stderr) {
ex = new Error('stderr maxBuffer exceeded'); if (encoding)
kill(); child.stderr.setEncoding(encoding);
} else {
if (!encoding)
_stderr.push(chunk);
else
_stderr += chunk;
}
});
if (encoding) { child.stderr.addListener('data', function(chunk) {
child.stderr.setEncoding(encoding); stderrLen += chunk.length;
child.stdout.setEncoding(encoding);
if (stderrLen > options.maxBuffer) {
ex = new Error('stderr maxBuffer exceeded');
kill();
} else {
if (!encoding)
_stderr.push(chunk);
else
_stderr += chunk;
}
});
} }
child.addListener('close', exithandler); child.addListener('close', exithandler);