Skip to content

Commit 8ab4cb9

Browse files
committed
vfs: reject a repeated --vfs-load
--vfs-load appends to the same list as --vfs-mount, so the parsed options cannot say how often it was given, and a second one quietly won over the first instead of being refused. The documentation already said it may be given at most once. Count it in the node options the command line yielded and error when there is more than one. Repeating --vfs-mount stays allowed; only the option that picks the entry point is limited. Signed-off-by: Philipp Dunkel <pip@pipobscure.com>
1 parent a5d00cc commit 8ab4cb9

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

‎src/node.cc‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,18 @@ static ExitCode InitializeNodeWithArgsInternal(
10241024
errors->push_back("--vfs-load requires --experimental-vfs");
10251025
}
10261026
}
1027+
// --vfs-load shares vfs_mounts with --vfs-mount, so the options themselves
1028+
// cannot say how often it was given; count it in the node options the
1029+
// command line yielded. A second one would silently win over the first.
1030+
if (env_options->vfs_load && exec_argv != nullptr) {
1031+
size_t seen = 0;
1032+
for (const std::string& arg : *exec_argv) {
1033+
if (arg == "--vfs-load" || arg.starts_with("--vfs-load=")) seen++;
1034+
}
1035+
if (seen > 1) {
1036+
errors->push_back("--vfs-load may only be given once");
1037+
}
1038+
}
10271039
if (!errors->empty()) return ExitCode::kInvalidCommandLineArgument;
10281040
}
10291041

‎test/parallel/test-vfs-mount-load.js‎

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,30 @@ require('worker_threads').parentPort.postMessage('hello from worker in mount');
211211
assert.notStrictEqual(first, second);
212212
}
213213

214+
// --vfs-load may only be given once: it shares one list with --vfs-mount, so a
215+
// second one would otherwise quietly win over the first.
216+
{
217+
const dirs = {};
218+
for (const name of ['once-a', 'once-b']) {
219+
dirs[name] = fixture(name);
220+
fs.mkdirSync(dirs[name], { recursive: true });
221+
fs.writeFileSync(path.join(dirs[name], 'index.js'),
222+
`console.log('ran:${name}');\n`);
223+
}
224+
225+
const twice = run([`--vfs-load=${dirs['once-a']}`,
226+
`--vfs-load=${dirs['once-b']}`]);
227+
assert.notStrictEqual(twice.status, 0);
228+
assert.match(twice.stderr, /--vfs-load may only be given once/);
229+
230+
// Repeating --vfs-mount stays allowed; only the loading one is limited.
231+
const many = run([`--vfs-mount=${dirs['once-a']}`,
232+
`--vfs-load=${dirs['once-b']}`,
233+
`--vfs-mount=${dirs['once-a']}`]);
234+
assert.strictEqual(many.status, 0, many.stderr);
235+
assert.match(many.stdout, /ran:once-b/);
236+
}
237+
214238
// --vfs-load picks the entry point, so it is refused in NODE_OPTIONS: the
215239
// environment must not be able to redirect what a `node <args>` run executes.
216240
// Everything but the flag under test is passed on the command line, so a build
@@ -220,12 +244,25 @@ if (hasNodeOptions) {
220244
fs.mkdirSync(dir, { recursive: true });
221245
fs.writeFileSync(path.join(dir, 'index.js'), 'console.log("ran");\n');
222246

223-
const res = spawnSync(
224-
process.execPath, ['--experimental-vfs'],
225-
{ encoding: 'utf8',
226-
env: { ...process.env, NODE_OPTIONS: envArg('--vfs-load', dir) } });
227-
assert.notStrictEqual(res.status, 0);
228-
assert.match(res.stderr, /is not allowed in NODE_OPTIONS/);
247+
// On its own, and alongside a --vfs-load the command line legitimately gave:
248+
// the environment is refused either way rather than merged.
249+
for (const args of [['--experimental-vfs'],
250+
['--experimental-vfs', `--vfs-load=${dir}`]]) {
251+
const res = spawnSync(process.execPath, args, {
252+
encoding: 'utf8',
253+
env: { ...process.env, NODE_OPTIONS: envArg('--vfs-load', dir) },
254+
});
255+
assert.notStrictEqual(res.status, 0);
256+
assert.match(res.stderr, /--vfs-load.* is not allowed in NODE_OPTIONS/);
257+
}
258+
259+
// --vfs-mount, by contrast, is accepted from the environment.
260+
const mountFromEnv = spawnSync(
261+
process.execPath, ['--experimental-vfs', `--vfs-load=${dir}`], {
262+
encoding: 'utf8',
263+
env: { ...process.env, NODE_OPTIONS: envArg('--vfs-mount', dir) },
264+
});
265+
assert.strictEqual(mountFromEnv.status, 0, mountFromEnv.stderr);
229266
}
230267

231268
// --experimental-vfs and --vfs-mount may arrive from different places. The

0 commit comments

Comments
 (0)