Skip to content

Commit 7bd96e3

Browse files
aduh95juanarbol
authored andcommitted
src: escape Windows environment variables in task runner
Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com> PR-URL: #65217 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Tierney Cyren <hello@bnb.im> Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
1 parent 3436da1 commit 7bd96e3

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

src/node_task_runner.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ std::string EscapeShell(const std::string_view input) {
150150
}
151151

152152
static constexpr std::string_view forbidden_characters =
153-
"[\t\n\r \"#$&'()*;<>?\\\\`|~]";
153+
"[\t\n\r \"#$&'()*;<>%?\\\\`|~]";
154154

155155
// Check if input contains any forbidden characters
156156
// If it doesn't, return the input as is.
@@ -170,6 +170,7 @@ std::string EscapeShell(const std::string_view input) {
170170
static const std::regex tripleSingleQuote("\\\\\"\"\"");
171171
escaped = std::regex_replace(escaped, leadingQuotePairs, "");
172172
escaped = std::regex_replace(escaped, tripleSingleQuote, "\\\"");
173+
escaped = std::regex_replace(escaped, std::regex("%"), "^%");
173174
#else
174175
// Replace single quotes("'") with "\\'" and wrap the result
175176
// in single quotes.

test/parallel/test-node-run.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const assert = require('node:assert');
99
const fixtures = require('../common/fixtures');
1010
const envSuffix = common.isWindows ? '-windows' : '';
1111

12-
describe('node --run [command]', () => {
12+
describe('node --run [command]', { concurrency: !process.env.TEST_PARALLEL }, () => {
1313
it('returns error on non-existent file', async () => {
1414
const child = await common.spawnPromisified(
1515
process.execPath,
@@ -222,4 +222,19 @@ describe('node --run [command]', () => {
222222
assert.strictEqual(child.stdout, '');
223223
assert.strictEqual(child.code, 1);
224224
});
225+
226+
it('escapes shell characters', async () => {
227+
const child = await common.spawnPromisified(
228+
process.execPath,
229+
[ '--run', `positional-args${envSuffix}`, '--', '%PAYLOAD%', '$PAYLOAD'],
230+
{ cwd: fixtures.path('run-script'), env: { ...process.env, PAYLOAD: 'env value' } },
231+
);
232+
assert.strictEqual(
233+
child.stdout,
234+
common.isWindows ?
235+
`Raw '"^%PAYLOAD^%" "$PAYLOAD"'\r\nArguments: '%PAYLOAD% $PAYLOAD'\r\nThe total number of arguments are: 2\r\n` :
236+
"Arguments: '%PAYLOAD% $PAYLOAD'\nThe total number of arguments are: 2\n");
237+
assert.strictEqual(child.stderr, '');
238+
assert.strictEqual(child.code, 0);
239+
});
225240
});

0 commit comments

Comments
 (0)