Skip to content

Commit

Permalink
child_process: validate strings in exec and spawn
Browse files Browse the repository at this point in the history
  • Loading branch information
puskin94 committed Dec 11, 2024
1 parent c4aa34a commit a3b5b1a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 12 deletions.
18 changes: 10 additions & 8 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,6 @@ function _forkChild(fd, serializationMode) {
}

function normalizeExecArgs(command, options, callback) {
validateString(command, 'command');
validateArgumentNullCheck(command, 'command');

if (typeof options === 'function') {
callback = options;
options = undefined;
Expand Down Expand Up @@ -535,12 +532,17 @@ function copyProcessEnvToEnv(env, name, optionEnv) {
}
}

function normalizeSpawnArguments(file, args, options) {
validateString(file, 'file');
validateArgumentNullCheck(file, 'file');
function validateStringParam(param, paramName) {
validateString(param, paramName);
validateArgumentNullCheck(param, paramName);

if (param.length === 0) {
throw new ERR_INVALID_ARG_VALUE(paramName, param, 'cannot be empty');
}
}

if (file.length === 0)
throw new ERR_INVALID_ARG_VALUE('file', file, 'cannot be empty');
function normalizeSpawnArguments(file, args, options) {
validateStringParam(file, 'file');

if (ArrayIsArray(args)) {
args = ArrayPrototypeSlice(args);
Expand Down
40 changes: 36 additions & 4 deletions test/parallel/test-child-process-exec-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const child_process = require('child_process');
const { exec, execSync, execFile } = require('child_process');

function test(fn, code, expectPidType = 'number') {
const child = fn('does-not-exist', common.mustCall(function(err) {
Expand All @@ -35,10 +35,42 @@ function test(fn, code, expectPidType = 'number') {

// With `shell: true`, expect pid (of the shell)
if (common.isWindows) {
test(child_process.exec, 1, 'number'); // Exit code of cmd.exe
test(exec, 1, 'number'); // Exit code of cmd.exe
} else {
test(child_process.exec, 127, 'number'); // Exit code of /bin/sh
test(exec, 127, 'number'); // Exit code of /bin/sh
}

// With `shell: false`, expect no pid
test(child_process.execFile, 'ENOENT', 'undefined');
test(execFile, 'ENOENT', 'undefined');


// Verify that the exec() function throws when command parameter is not a valid string
{
assert.throws(() => {
exec(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
exec('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
exec('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}


// Verify that the execSync() function throws when command parameter is not a valid string
{
assert.throws(() => {
execSync(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
execSync('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
execSync('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}
30 changes: 30 additions & 0 deletions test/parallel/test-child-process-execfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,33 @@ const execOpts = { encoding: 'utf8', shell: true, env: { ...process.env, NODE: p
}));
});
}

// Verify that the execFile() function throws when the file parameter is not a valid string
{
assert.throws(() => {
execFile(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
execFile('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
execFile('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}

// Verify that the execFileSync() function throws when file parameter is not a valid string
{
assert.throws(() => {
execFileSync(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
execFileSync('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
execFileSync('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}
16 changes: 16 additions & 0 deletions test/parallel/test-child-process-spawn-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,19 @@ enoentChild.on('error', common.mustCall(function(err) {
assert.strictEqual(err.path, enoentPath);
assert.deepStrictEqual(err.spawnargs, spawnargs);
}));


// Verify that the spawn() function throws when the file parameter is not a valid string
{
assert.throws(() => {
spawn(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
spawn('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
spawn('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}
15 changes: 15 additions & 0 deletions test/parallel/test-child-process-spawnsync.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,18 @@ assert.deepStrictEqual(ret_err.spawnargs, ['bar']);
];
assert.deepStrictEqual(retUTF8.output, stringifiedDefault);
}

// Verify that the spawnSync() function throws when the file parameter is not a valid string
{
assert.throws(() => {
spawnSync(123, common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_TYPE' });

assert.throws(() => {
spawnSync('', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });

assert.throws(() => {
spawnSync('\u0000', common.mustNotCall());
}, { code: 'ERR_INVALID_ARG_VALUE' });
}

0 comments on commit a3b5b1a

Please sign in to comment.