diff --git a/test/fuzz/exec-file.test.cjs b/test/fuzz/exec-file.test.cjs index 9ac54eddb..378b6b8fe 100644 --- a/test/fuzz/exec-file.test.cjs +++ b/test/fuzz/exec-file.test.cjs @@ -5,74 +5,79 @@ */ const assert = require("node:assert"); -const { execFileSync } = require("node:child_process"); +const { execFile, execFileSync } = require("node:child_process"); const common = require("./_common.cjs"); const shescape = require("../../index.cjs"); -function check(arg) { - const shell = common.getFuzzShell(); +function check({ arg, shell }) { const argInfo = { arg, shell, quoted: Boolean(shell) }; const execFileOptions = { encoding: "utf8", shell }; const preparedArg = common.prepareArg(argInfo, !Boolean(shell)); + const safeArg = execFileOptions.shell + ? shescape.quote(preparedArg, execFileOptions) + : shescape.escape(preparedArg, execFileOptions); - const stdout = execFileSync( - "node", - execFileOptions.shell - ? shescape.quoteAll([common.ECHO_SCRIPT, preparedArg], execFileOptions) - : shescape.escapeAll([common.ECHO_SCRIPT, preparedArg], execFileOptions), - execFileOptions - ); - - const result = stdout; - const expected = common.getExpectedOutput(argInfo); - assert.strictEqual(result, expected); + return new Promise((resolve, reject) => { + execFile( + "node", + [common.ECHO_SCRIPT, safeArg], + execFileOptions, + (error, stdout) => { + if (error) { + reject(`an unexpected error occurred: ${error}`); + } else { + const result = stdout; + const expected = common.getExpectedOutput(argInfo); + try { + assert.strictEqual(result, expected); + resolve(); + } catch (e) { + reject(e); + } + } + } + ); + }); } -function checkMultipleArgs(args) { - const shell = common.getFuzzShell(); - const argInfo = { shell, quoted: Boolean(shell) }; +function checkSync({ arg, shell }) { + const argInfo = { arg, shell, quoted: Boolean(shell) }; const execFileOptions = { encoding: "utf8", shell }; - const preparedArgs = args.map((arg) => - common.prepareArg({ ...argInfo, arg }, !Boolean(shell)) - ); + const preparedArg = common.prepareArg(argInfo, !Boolean(shell)); + const safeArg = execFileOptions.shell + ? shescape.quote(preparedArg, execFileOptions) + : shescape.escape(preparedArg, execFileOptions); - const stdout = execFileSync( - "node", - execFileOptions.shell - ? shescape.quoteAll( - [common.ECHO_SCRIPT, ...preparedArgs], - execFileOptions - ) - : shescape.escapeAll( - [common.ECHO_SCRIPT, ...preparedArgs], - execFileOptions - ), - execFileOptions - ); + let stdout; + try { + stdout = execFileSync( + "node", + [common.ECHO_SCRIPT, safeArg], + execFileOptions + ); + } catch (error) { + assert.fail(`an unexpected error occurred: ${error}`); + } const result = stdout; - const expected = common.getExpectedOutput({ - ...argInfo, - arg: (common.isShellPowerShell(shell) - ? args.filter( - (arg) => arg.replace(/[\0\u0008\u001B\u009B]/gu, "").length !== 0 - ) - : args - ).join(" "), - }); + const expected = common.getExpectedOutput(argInfo); assert.strictEqual(result, expected); } -function fuzz(buf) { +async function fuzz(buf) { const arg = buf.toString(); - const args = arg.split(/[\n\r]+/u); + const shell = common.getFuzzShell(); - check(arg); - checkMultipleArgs(args); + try { + await check({ arg, shell }); + checkSync({ arg, shell }); + } catch (e) { + throw e; + } } module.exports = { diff --git a/test/fuzz/exec.test.cjs b/test/fuzz/exec.test.cjs index 917ba782e..1ebbb0627 100644 --- a/test/fuzz/exec.test.cjs +++ b/test/fuzz/exec.test.cjs @@ -5,14 +5,13 @@ */ const assert = require("node:assert"); -const { execSync } = require("node:child_process"); +const { exec, execSync } = require("node:child_process"); const common = require("./_common.cjs"); const shescape = require("../../index.cjs"); -function check(arg) { - const shell = common.getFuzzShell(); +function check({ arg, shell }) { const argInfo = { arg, shell, quoted: true }; const execOptions = { encoding: "utf8", shell }; @@ -21,18 +20,50 @@ function check(arg) { ...execOptions, }); - const stdout = execSync( - `node ${common.ECHO_SCRIPT} ${quotedArg}`, - execOptions - ); + return new Promise((resolve, reject) => { + exec( + `node ${common.ECHO_SCRIPT} ${quotedArg}`, + execOptions, + (error, stdout) => { + if (error) { + reject(`an unexpected error occurred: ${error}`); + } else { + const result = stdout; + const expected = common.getExpectedOutput(argInfo); + try { + assert.strictEqual(result, expected); + resolve(); + } catch (e) { + reject(e); + } + } + } + ); + }); +} + +function checkSync({ arg, shell }) { + const argInfo = { arg, shell, quoted: true }; + const execOptions = { encoding: "utf8", shell }; + + const preparedArg = common.prepareArg(argInfo); + const quotedArg = shescape.quote(preparedArg, { + ...execOptions, + }); + + let stdout; + try { + stdout = execSync(`node ${common.ECHO_SCRIPT} ${quotedArg}`, execOptions); + } catch (error) { + assert.fail(`an unexpected error occurred: ${error}`); + } const result = stdout; const expected = common.getExpectedOutput(argInfo); assert.strictEqual(result, expected); } -function checkUsingInterpolation(arg) { - const shell = common.getFuzzShell(); +function checkUsingInterpolation({ arg, shell }) { const argInfo = { arg, shell, quoted: false }; const execOptions = { encoding: "utf8", shell }; @@ -42,21 +73,62 @@ function checkUsingInterpolation(arg) { interpolation: true, }); - const stdout = execSync( - `node ${common.ECHO_SCRIPT} ${escapedArg}`, - execOptions - ); + return new Promise((resolve, reject) => { + exec( + `node ${common.ECHO_SCRIPT} ${escapedArg}`, + execOptions, + (error, stdout) => { + if (error) { + reject(`an unexpected error occurred: ${error}`); + } else { + const result = stdout; + const expected = common.getExpectedOutput(argInfo, true); + try { + assert.strictEqual(result, expected); + resolve(); + } catch (e) { + reject(e); + } + } + } + ); + }); +} + +function checkUsingInterpolationSync({ arg, shell }) { + const argInfo = { arg, shell, quoted: false }; + const execOptions = { encoding: "utf8", shell }; + + const preparedArg = common.prepareArg(argInfo); + const escapedArg = shescape.escape(preparedArg, { + ...execOptions, + interpolation: true, + }); + + let stdout; + try { + stdout = execSync(`node ${common.ECHO_SCRIPT} ${escapedArg}`, execOptions); + } catch (error) { + assert.fail(`an unexpected error occurred: ${error}`); + } const result = stdout; const expected = common.getExpectedOutput(argInfo, true); assert.strictEqual(result, expected); } -function fuzz(buf) { +async function fuzz(buf) { const arg = buf.toString(); + const shell = common.getFuzzShell(); - check(arg); - checkUsingInterpolation(arg); + try { + await check({ arg, shell }); + await checkUsingInterpolation({ arg, shell }); + checkSync({ arg, shell }); + checkUsingInterpolationSync({ arg, shell }); + } catch (e) { + throw e; + } } module.exports = { diff --git a/test/fuzz/fork.test.cjs b/test/fuzz/fork.test.cjs index 0c6a2351e..54ba5ba6a 100644 --- a/test/fuzz/fork.test.cjs +++ b/test/fuzz/fork.test.cjs @@ -16,48 +16,18 @@ function check(arg) { const forkOptions = { silent: true }; const preparedArg = common.prepareArg(argInfo, true); + const safeArg = shescape.escape(preparedArg); return new Promise((resolve, reject) => { - const echo = fork( - common.ECHO_SCRIPT, - shescape.escapeAll([preparedArg]), - forkOptions - ); + const echo = fork(common.ECHO_SCRIPT, [safeArg], forkOptions); - echo.stdout.on("data", (data) => { - const result = data.toString(); - const expected = common.getExpectedOutput(argInfo); - try { - assert.strictEqual(result, expected); - resolve(); - } catch (e) { - reject(e); - } + echo.on("error", (error) => { + reject(`an unexpected error occurred: ${error}`); }); - }); -} - -function checkMultipleArgs(args) { - const argInfo = { quoted: false }; - const forkOptions = { silent: true }; - - const preparedArgs = args.map((arg) => - common.prepareArg({ ...argInfo, arg }, true) - ); - - return new Promise((resolve, reject) => { - const echo = fork( - common.ECHO_SCRIPT, - shescape.escapeAll(preparedArgs), - forkOptions - ); echo.stdout.on("data", (data) => { const result = data.toString(); - const expected = common.getExpectedOutput({ - ...argInfo, - arg: args.join(" "), - }); + const expected = common.getExpectedOutput(argInfo); try { assert.strictEqual(result, expected); resolve(); @@ -70,11 +40,9 @@ function checkMultipleArgs(args) { async function fuzz(buf) { const arg = buf.toString(); - const args = arg.split(/[\n\r]+/u); try { await check(arg); - await checkMultipleArgs(args); } catch (e) { throw e; } diff --git a/test/fuzz/spawn.test.cjs b/test/fuzz/spawn.test.cjs index 119ebd2e1..476022115 100644 --- a/test/fuzz/spawn.test.cjs +++ b/test/fuzz/spawn.test.cjs @@ -5,68 +5,71 @@ */ const assert = require("node:assert"); -const { spawnSync } = require("node:child_process"); +const { spawn, spawnSync } = require("node:child_process"); const common = require("./_common.cjs"); const shescape = require("../../index.cjs"); -function check(arg) { - const shell = common.getFuzzShell(); +function check({ arg, shell }) { const argInfo = { arg, shell, quoted: Boolean(shell) }; const spawnOptions = { encoding: "utf8", shell }; const preparedArg = common.prepareArg(argInfo, !Boolean(shell)); + const safeArg = spawnOptions.shell + ? shescape.quote(preparedArg, spawnOptions) + : shescape.escape(preparedArg, spawnOptions); + + return new Promise((resolve, reject) => { + const child = spawn("node", [common.ECHO_SCRIPT, safeArg], spawnOptions); - const child = spawnSync( - "node", - spawnOptions.shell - ? shescape.quoteAll([common.ECHO_SCRIPT, preparedArg], spawnOptions) - : shescape.escapeAll([common.ECHO_SCRIPT, preparedArg], spawnOptions), - spawnOptions - ); + child.on("error", (error) => { + reject(`an unexpected error occurred: ${error}`); + }); - const result = child.stdout; - const expected = common.getExpectedOutput(argInfo); - assert.strictEqual(result, expected); + child.stdout.on("data", (data) => { + const result = data.toString(); + const expected = common.getExpectedOutput(argInfo); + try { + assert.strictEqual(result, expected); + resolve(); + } catch (e) { + reject(e); + } + }); + }); } -function checkMultipleArgs(args) { - const shell = common.getFuzzShell(); - const argInfo = { shell, quoted: Boolean(shell) }; +function checkSync({ arg, shell }) { + const argInfo = { arg, shell, quoted: Boolean(shell) }; const spawnOptions = { encoding: "utf8", shell }; - const preparedArgs = args.map((arg) => - common.prepareArg({ ...argInfo, arg }, !Boolean(shell)) - ); + const preparedArg = common.prepareArg(argInfo, !Boolean(shell)); + const safeArg = spawnOptions.shell + ? shescape.quote(preparedArg, spawnOptions) + : shescape.escape(preparedArg, spawnOptions); - const child = spawnSync( - "node", - spawnOptions.shell - ? shescape.quoteAll([common.ECHO_SCRIPT, ...preparedArgs], spawnOptions) - : shescape.escapeAll([common.ECHO_SCRIPT, ...preparedArgs], spawnOptions), - spawnOptions - ); + const child = spawnSync("node", [common.ECHO_SCRIPT, safeArg], spawnOptions); - const result = child.stdout; - const expected = common.getExpectedOutput({ - ...argInfo, - arg: (common.isShellPowerShell(shell) - ? args.filter( - (arg) => arg.replace(/[\0\u0008\u001B\u009B]/gu, "").length !== 0 - ) - : args - ).join(" "), - }); - assert.strictEqual(result, expected); + if (child.error) { + assert.fail(`an unexpected error occurred: ${child.error}`); + } else { + const result = child.stdout; + const expected = common.getExpectedOutput(argInfo); + assert.strictEqual(result, expected); + } } -function fuzz(buf) { +async function fuzz(buf) { const arg = buf.toString(); - const args = arg.split(/[\n\r]+/u); + const shell = common.getFuzzShell(); - check(arg); - checkMultipleArgs(args); + try { + await check({ arg, shell }); + checkSync({ arg, shell }); + } catch (e) { + throw e; + } } module.exports = {