mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
src: allows escaping NODE_OPTIONS with backslashes
The characters specified within NODE_OPTIONS can now be escaped, which is handy especially in conjunction with `--require` (where the file path might happen to contain spaces that shouldn't cause the option to be split into two). Fixes: https://github.com/nodejs/node/issues/12971 PR-URL: https://github.com/nodejs/node/pull/24065 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
ba74e42000
commit
3ef1512f9e
@ -774,6 +774,13 @@ if they had been specified on the command line before the actual command line
|
||||
(so they can be overridden). Node.js will exit with an error if an option
|
||||
that is not allowed in the environment is used, such as `-p` or a script file.
|
||||
|
||||
In case an option value happens to contain a space (for example a path listed in
|
||||
`--require`), it must be escaped using double quotes. For example:
|
||||
|
||||
```bash
|
||||
--require "./my path/file.js"
|
||||
```
|
||||
|
||||
Node.js options that are allowed are:
|
||||
- `--diagnostic-report-directory`
|
||||
- `--diagnostic-report-filename`
|
||||
|
46
src/node.cc
46
src/node.cc
@ -671,11 +671,49 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
|
||||
|
||||
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
|
||||
std::string node_options;
|
||||
|
||||
if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
|
||||
// [0] is expected to be the program name, fill it in from the real argv
|
||||
// and use 'x' as a placeholder while parsing.
|
||||
std::vector<std::string> env_argv = SplitString("x " + node_options, ' ');
|
||||
env_argv[0] = argv->at(0);
|
||||
std::vector<std::string> env_argv;
|
||||
// [0] is expected to be the program name, fill it in from the real argv.
|
||||
env_argv.push_back(argv->at(0));
|
||||
|
||||
bool is_in_string = false;
|
||||
bool will_start_new_arg = true;
|
||||
for (std::string::size_type index = 0;
|
||||
index < node_options.size();
|
||||
++index) {
|
||||
char c = node_options.at(index);
|
||||
|
||||
// Backslashes escape the following character
|
||||
if (c == '\\' && is_in_string) {
|
||||
if (index + 1 == node_options.size()) {
|
||||
errors->push_back("invalid value for NODE_OPTIONS "
|
||||
"(invalid escape)\n");
|
||||
return 9;
|
||||
} else {
|
||||
c = node_options.at(++index);
|
||||
}
|
||||
} else if (c == ' ' && !is_in_string) {
|
||||
will_start_new_arg = true;
|
||||
continue;
|
||||
} else if (c == '"') {
|
||||
is_in_string = !is_in_string;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (will_start_new_arg) {
|
||||
env_argv.push_back(std::string(1, c));
|
||||
will_start_new_arg = false;
|
||||
} else {
|
||||
env_argv.back() += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_in_string) {
|
||||
errors->push_back("invalid value for NODE_OPTIONS "
|
||||
"(unterminated string)\n");
|
||||
return 9;
|
||||
}
|
||||
|
||||
const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
|
||||
if (exit_code != 0) return exit_code;
|
||||
|
1
test/fixtures/print A.js
vendored
Normal file
1
test/fixtures/print A.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
console.log('A')
|
@ -12,7 +12,12 @@ const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
const printA = require.resolve('../fixtures/printA.js');
|
||||
const printSpaceA = require.resolve('../fixtures/print A.js');
|
||||
|
||||
expect(` -r ${printA} `, 'A\nB\n');
|
||||
expect(`-r ${printA}`, 'A\nB\n');
|
||||
expect(`-r ${JSON.stringify(printA)}`, 'A\nB\n');
|
||||
expect(`-r ${JSON.stringify(printSpaceA)}`, 'A\nB\n');
|
||||
expect(`-r ${printA} -r ${printA}`, 'A\nB\n');
|
||||
expect(` -r ${printA} -r ${printA}`, 'A\nB\n');
|
||||
expect(` --require ${printA} --require ${printA}`, 'A\nB\n');
|
||||
|
Loading…
Reference in New Issue
Block a user