summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaƫl Nison <mael@fb.com>2018-11-03 10:52:44 -0700
committerAnna Henningsen <anna@addaleax.net>2019-04-17 19:46:00 +0200
commit3ef1512f9e416cc7656b9cd16934dffdee1b11d3 (patch)
tree440c5d413cf9e628c1556a89d2b798acd445403f
parentba74e42000418bf9e8263123fc7291c19e1d5425 (diff)
downloadandroid-node-v8-3ef1512f9e416cc7656b9cd16934dffdee1b11d3.tar.gz
android-node-v8-3ef1512f9e416cc7656b9cd16934dffdee1b11d3.tar.bz2
android-node-v8-3ef1512f9e416cc7656b9cd16934dffdee1b11d3.zip
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>
-rw-r--r--doc/api/cli.md7
-rw-r--r--src/node.cc46
-rw-r--r--test/fixtures/print A.js1
-rw-r--r--test/parallel/test-cli-node-options.js5
4 files changed, 55 insertions, 4 deletions
diff --git a/doc/api/cli.md b/doc/api/cli.md
index 79f2dcd2ba..a2c92b1334 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -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`
diff --git a/src/node.cc b/src/node.cc
index 53a9ae397b..c3b0a50e38 100644
--- a/src/node.cc
+++ b/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;
diff --git a/test/fixtures/print A.js b/test/fixtures/print A.js
new file mode 100644
index 0000000000..30a56425de
--- /dev/null
+++ b/test/fixtures/print A.js
@@ -0,0 +1 @@
+console.log('A')
diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js
index d3d1938bf8..07b69c5b13 100644
--- a/test/parallel/test-cli-node-options.js
+++ b/test/parallel/test-cli-node-options.js
@@ -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');