Skip to content

Commit 661cc49

Browse files
authored
os: fix args quoting in win_spawn_process (fix #26261) (#26339)
1 parent ab89a21 commit 661cc49

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

‎cmd/tools/test_os_args.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
println(arguments()#[1..])

‎vlib/os/process_args_test.v‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import os
2+
3+
const vexe = os.getenv('VEXE')
4+
const vroot = os.dir(vexe)
5+
6+
fn test_v_run_simple() {
7+
echo_os_args := os.join_path(vroot, 'cmd/tools/test_os_args.v')
8+
res123 := os.execute('${os.quoted_path(vexe)} run ${os.quoted_path(echo_os_args)} 1 2 3')
9+
println(res123)
10+
assert res123.exit_code == 0
11+
assert res123.output.starts_with("['1', '2', '3']")
12+
}
13+
14+
fn test_v_run_quoted_args_with_spaces() {
15+
echo_os_args := os.join_path(vroot, 'cmd/tools/test_os_args.v')
16+
res := os.execute('${os.quoted_path(vexe)} run ${os.quoted_path(echo_os_args)} 1 "Learn V" 3')
17+
println(res)
18+
assert res.exit_code == 0
19+
assert res.output.starts_with("['1', 'Learn V', '3']")
20+
}

‎vlib/os/process_windows.c.v‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ fn (mut p Process) win_spawn_process() int {
108108
start_info.h_std_error = wdata.child_stderr_write
109109
start_info.dw_flags = u32(C.STARTF_USESTDHANDLES)
110110
}
111-
cmd := '${p.filename} ' + p.args.join(' ')
111+
cmd := '${p.filename} ' + requote_args(p.args)
112112
cmd_wide_ptr := cmd.to_wide()
113113
to_be_freed << cmd_wide_ptr
114114
C.ExpandEnvironmentStringsW(cmd_wide_ptr, voidptr(&wdata.command_line[0]), 32768)
@@ -367,3 +367,23 @@ fn (mut p Process) unix_wait() {
367367
fn (mut p Process) unix_is_alive() bool {
368368
return false
369369
}
370+
371+
@[manualfree]
372+
fn requote_args(cargs []string) string {
373+
mut sb := strings.new_builder(128)
374+
defer { unsafe { sb.free() } }
375+
for idx, a in cargs {
376+
if idx > 0 {
377+
sb.write_rune(` `)
378+
}
379+
if !a.starts_with('"') {
380+
sb.write_string('"')
381+
sb.write_string(a)
382+
sb.write_string('"')
383+
} else {
384+
sb.write_string(a)
385+
}
386+
}
387+
res := sb.str()
388+
return res
389+
}

0 commit comments

Comments
 (0)