Skip to content

Commit 97a7728

Browse files
committed
child_process: improve ChildProcess validation
This commit improves input validation for the ChildProcess internals. It became officially supported API a while back, but never had any validation. Refs: #12177 PR-URL: #12348 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Santiago Gimeno <[email protected]>
1 parent 59c6230 commit 97a7728

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

‎lib/internal/child_process.js‎

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ ChildProcess.prototype.spawn = function(options){
254254
varipcFd;
255255
vari;
256256

257+
if(options===null||typeofoptions!=='object')
258+
thrownewTypeError('"options" must be an object');
259+
257260
// If no `stdio` option was given - use default
258261
varstdio=options.stdio||'pipe';
259262

@@ -265,12 +268,25 @@ ChildProcess.prototype.spawn = function(options){
265268

266269
if(ipc!==undefined){
267270
// Let child process know about opened IPC channel
268-
options.envPairs=options.envPairs||[];
271+
if(options.envPairs===undefined)
272+
options.envPairs=[];
273+
elseif(!Array.isArray(options.envPairs))
274+
thrownewTypeError('"envPairs" must be an array');
275+
269276
options.envPairs.push('NODE_CHANNEL_FD='+ipcFd);
270277
}
271278

272-
this.spawnfile=options.file;
273-
this.spawnargs=options.args;
279+
if(typeofoptions.file==='string')
280+
this.spawnfile=options.file;
281+
else
282+
thrownewTypeError('"file" must be a string');
283+
284+
if(Array.isArray(options.args))
285+
this.spawnargs=options.args;
286+
elseif(options.args===undefined)
287+
this.spawnargs=[];
288+
else
289+
thrownewTypeError('"args" must be an array');
274290

275291
varerr=this._handle.spawn(options);
276292

‎test/parallel/test-child-process-constructor.js‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,50 @@ const assert = require('assert');
55
const{ ChildProcess }=require('child_process');
66
assert.strictEqual(typeofChildProcess,'function');
77

8+
{
9+
// Verify that invalid options to spawn() throw.
10+
constchild=newChildProcess();
11+
12+
[undefined,null,'foo',0,1,NaN,true,false].forEach((options)=>{
13+
assert.throws(()=>{
14+
child.spawn(options);
15+
},/^TypeError:"options"mustbeanobject$/);
16+
});
17+
}
18+
19+
{
20+
// Verify that spawn throws if file is not a string.
21+
constchild=newChildProcess();
22+
23+
[undefined,null,0,1,NaN,true,false,{}].forEach((file)=>{
24+
assert.throws(()=>{
25+
child.spawn({ file });
26+
},/^TypeError:"file"mustbeastring$/);
27+
});
28+
}
29+
30+
{
31+
// Verify that spawn throws if envPairs is not an array or undefined.
32+
constchild=newChildProcess();
33+
34+
[null,0,1,NaN,true,false,{},'foo'].forEach((envPairs)=>{
35+
assert.throws(()=>{
36+
child.spawn({ envPairs,stdio: ['ignore','ignore','ignore','ipc']});
37+
},/^TypeError:"envPairs"mustbeanarray$/);
38+
});
39+
}
40+
41+
{
42+
// Verify that spawn throws if args is not an array or undefined.
43+
constchild=newChildProcess();
44+
45+
[null,0,1,NaN,true,false,{},'foo'].forEach((args)=>{
46+
assert.throws(()=>{
47+
child.spawn({file: 'foo', args });
48+
},/^TypeError:"args"mustbeanarray$/);
49+
});
50+
}
51+
852
// test that we can call spawn
953
constchild=newChildProcess();
1054
child.spawn({

0 commit comments

Comments
(0)