Skip to content

Commit b931733

Browse files
committed
test: add escapePOSIXShell util
1 parent 0f7bdcc commit b931733

File tree

47 files changed

+237
-334
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+237
-334
lines changed

test/abort/test-abort-fatal-error.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@ if (common.isWindows)
2727
const assert = require('assert');
2828
const exec = require('child_process').exec;
2929

30-
let cmdline = `ulimit -c 0; ${process.execPath}`;
31-
cmdline += ' --max-old-space-size=16 --max-semi-space-size=4';
32-
cmdline += ' -e "a = []; for (i = 0; i < 1e9; i++) { a.push({}) }"';
30+
const cmdline =
31+
common.escapePOSIXShell`ulimit -c 0; "${
32+
process.execPath
33+
}" --max-old-space-size=16 --max-semi-space-size=4 -e "a = []; for (i = 0; i < 1e9; i++) { a.push({}) }"`;
3334

34-
exec(cmdline, function(err, stdout, stderr) {
35+
exec(...cmdline, common.mustCall((err, stdout, stderr) => {
3536
if (!err) {
3637
console.log(stdout);
3738
console.log(stderr);
3839
assert(false, 'this test should fail');
3940
}
4041

4142
assert(common.nodeProcessAborted(err.code, err.signal));
42-
});
43+
}));

test/async-hooks/test-callback-error.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ assert.ok(!arg);
6262
let program = process.execPath;
6363
let args = [
6464
'--abort-on-uncaught-exception', __filename, 'test_callback_abort' ];
65-
const options = { encoding: 'utf8' };
65+
let options = { encoding: 'utf8' };
6666
if (!common.isWindows) {
67-
program = `ulimit -c 0 && exec ${program} ${args.join(' ')}`;
67+
[program, options] = common.escapePOSIXShell`ulimit -c 0 && exec "${program}" ${args[0]} "${args[1]}" ${args[2]}`;
6868
args = [];
6969
options.shell = true;
70+
options.encoding = 'utf8';
7071
}
7172
const child = spawnSync(program, args, options);
7273
if (common.isWindows) {

test/common/escapePOSIXShell.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
/**
4+
* Escape quoted values in a string template literal. On Windows, this function
5+
* does not escape anything (which is fine for paths, as `"` is not a valid char
6+
* in a path on Windows), so you should use it only to escape paths – or other
7+
* values on tests which are skipped on Windows.
8+
* @returns {[string, object | undefined]} An array that can be passed as
9+
* arguments to `exec` or `execSync`.
10+
*/
11+
module.exports = function escapePOSIXShell(cmdParts, ...args) {
12+
if (common.isWindows) {
13+
// On Windows, paths cannot contain `"`, so we can return the string unchanged.
14+
return [String.raw({ raw: cmdParts }, ...args)];
15+
}
16+
// On POSIX shells, we can pass values via the env, as there's a standard way for referencing a variable.
17+
const env = { ...process.env };
18+
let cmd = cmdParts[0];
19+
for (let i = 0; i < args.length; i++) {
20+
const envVarName = `ESCAPED_${i}`;
21+
env[envVarName] = args[i];
22+
cmd += '${' + envVarName + '}' + cmdParts[i + 1];
23+
}
24+
25+
return [cmd, { env }];
26+
};

test/common/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const { inspect, getCallSite } = require('util');
3434
const { isMainThread } = require('worker_threads');
3535
const { isModuleNamespaceObject } = require('util/types');
3636

37+
const escapePOSIXShell = require('./escapePOSIXShell');
3738
const tmpdir = require('./tmpdir');
3839
const bits = ['arm64', 'loong64', 'mips', 'mipsel', 'ppc64', 'riscv64', 's390x', 'x64']
3940
.includes(process.arch) ? 64 : 32;
@@ -249,15 +250,13 @@ const PIPE = (() => {
249250
// `$node --abort-on-uncaught-exception $file child`
250251
// the process aborts.
251252
function childShouldThrowAndAbort() {
252-
let testCmd = '';
253+
const escapedArgs = escapePOSIXShell`"${process.argv[0]}" --abort-on-uncaught-exception "${process.argv[1]}" child`;
253254
if (!isWindows) {
254255
// Do not create core files, as it can take a lot of disk space on
255256
// continuous testing and developers' machines
256-
testCmd += 'ulimit -c 0 && ';
257+
escapedArgs[0] = 'ulimit -c 0 && ' + escapedArgs[0];
257258
}
258-
testCmd += `"${process.argv[0]}" --abort-on-uncaught-exception `;
259-
testCmd += `"${process.argv[1]}" child`;
260-
const child = exec(testCmd);
259+
const child = exec(...escapedArgs);
261260
child.on('exit', function onExit(exitCode, signal) {
262261
const errMsg = 'Test should have aborted ' +
263262
`but instead exited with exit code ${exitCode}` +
@@ -951,6 +950,7 @@ const common = {
951950
childShouldThrowAndAbort,
952951
createZeroFilledFile,
953952
defaultAutoSelectFamilyAttemptTimeout,
953+
escapePOSIXShell,
954954
expectsError,
955955
expectRequiredModule,
956956
expectWarning,

test/common/index.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
childShouldThrowAndAbort,
1212
createZeroFilledFile,
1313
enoughTestMem,
14+
escapePOSIXShell,
1415
expectsError,
1516
expectWarning,
1617
getArrayBufferViews,
@@ -64,6 +65,7 @@ export {
6465
createRequire,
6566
createZeroFilledFile,
6667
enoughTestMem,
68+
escapePOSIXShell,
6769
expectsError,
6870
expectWarning,
6971
getArrayBufferViews,

test/fixtures/snapshot/child-process-sync.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ const {
44
setDeserializeMainFunction,
55
isBuildingSnapshot
66
} = require('v8').startupSnapshot;
7+
const escapePOSIXShell = require('../../common/escapePOSIXShell');
78

89
function spawn() {
910
const { spawnSync, execFileSync, execSync } = require('child_process');
1011
spawnSync(process.execPath, [ __filename, 'spawnSync' ], { stdio: 'inherit' });
11-
execSync(`"${process.execPath}" "${__filename}" "execSync"`, { stdio: 'inherit' });
12+
const [cmd, opts] = escapePOSIXShell`"${process.execPath}" "${__filename}" "execSync"`;
13+
execSync(cmd, { ...opts, stdio: 'inherit'});
1214
execFileSync(process.execPath, [ __filename, 'execFileSync' ], { stdio: 'inherit' });
1315
}
1416

test/parallel/test-child-process-bad-stdio.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ ChildProcess.prototype.spawn = function() {
2727
};
2828

2929
function createChild(options, callback) {
30-
const cmd = `"${process.execPath}" "${__filename}" child`;
30+
const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" "${__filename}" child`;
31+
options = { ...options, env: { ...opts.env, ...options.env } };
3132

3233
return cp.exec(cmd, options, common.mustCall(callback));
3334
}

test/parallel/test-child-process-exec-encoding.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ if (process.argv[2] === 'child') {
1313
const expectedStdout = `${stdoutData}\n`;
1414
const expectedStderr = `${stderrData}\n`;
1515
function run(options, callback) {
16-
const cmd = `"${process.execPath}" "${__filename}" child`;
16+
const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" "${__filename}" child`;
17+
options = { ...options, env: { ...opts.env, ...options.env } };
1718

1819
cp.exec(cmd, options, common.mustSucceed((stdout, stderr) => {
1920
callback(stdout, stderr);

test/parallel/test-child-process-exec-maxbuf.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ function runChecks(err, stdio, streamName, expected) {
1414
// On non-Windows, we can pass the path via the env; `"` is not a valid char on
1515
// Windows, so we can simply pass the path.
1616
const execNode = (args, optionsOrCallback, callback) => {
17+
const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" `;
1718
let options = optionsOrCallback;
1819
if (typeof optionsOrCallback === 'function') {
1920
options = undefined;
2021
callback = optionsOrCallback;
2122
}
2223
return cp.exec(
23-
`"${common.isWindows ? process.execPath : '$NODE'}" ${args}`,
24-
common.isWindows ? options : { ...options, env: { ...process.env, NODE: process.execPath } },
24+
cmd + args,
25+
{ ...opts, ...options },
2526
callback,
2627
);
2728
};

test/parallel/test-child-process-exec-std-encoding.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ if (process.argv[2] === 'child') {
1212
console.log(stdoutData);
1313
console.error(stderrData);
1414
} else {
15-
const cmd = `"${process.execPath}" "${__filename}" child`;
16-
const child = cp.exec(cmd, common.mustSucceed((stdout, stderr) => {
15+
const child = cp.exec(...common.escapePOSIXShell`"${process.execPath}" "${__filename}" child`, common.mustSucceed((stdout, stderr) => {
1716
assert.strictEqual(stdout, expectedStdout);
1817
assert.strictEqual(stderr, expectedStderr);
1918
}));

0 commit comments

Comments
 (0)