Skip to content

Commit 4c271fc

Browse files
shell_parse: deprecate unescaped chars "#{}()[]<>|&*?~;" in commands
1 parent b3dfd0d commit 4c271fc

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

base/managers.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched,
185185
cmd = `cd $dir '&&' $tval $exename $exeflags`
186186

187187
# shell login (-l) with string command (-c) to launch julia process
188-
cmd = `sh -l -c $(shell_escape(cmd))`
188+
cmd = `sh -l -c $(shell_escape(cmd, special = ""))`
189189

190190
# remote launch with ssh with given ssh flags / host / port information
191191
# -T → disable pseudo-terminal allocation
@@ -195,7 +195,7 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched,
195195
# forwarded connections are causing collisions
196196
# -n → Redirects stdin from /dev/null (actually, prevents reading from stdin).
197197
# Used when running ssh in the background.
198-
cmd = `ssh -T -a -x -o ClearAllForwardings=yes -n $sshflags $host $(shell_escape(cmd))`
198+
cmd = `ssh -T -a -x -o ClearAllForwardings=yes -n $sshflags $host $(shell_escape(cmd, special = ""))`
199199

200200
# launch the remote Julia process
201201

base/process.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ end
9797
hash(x::AndCmds, h::UInt) = hash(x.a, hash(x.b, h))
9898
==(x::AndCmds, y::AndCmds) = x.a == y.a && x.b == y.b
9999

100-
shell_escape(cmd::Cmd) = shell_escape(cmd.exec...)
100+
shell_escape(cmd::Cmd; special::AbstractString=shell_special) =
101+
shell_escape(cmd.exec..., special=special)
101102

102103
function show(io::IO, cmd::Cmd)
103104
print_env = cmd.env !== nothing

base/shell.jl

+15-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## shell-like command parsing ##
44

5+
const shell_special = "#{}()[]<>|&*?~;"
6+
57
function shell_parse(str::AbstractString, interpolate::Bool=true)
68
s = lstrip(str)
79
# strips the end but respects the space when the string ends with "\\ "
@@ -92,6 +94,8 @@ function shell_parse(str::AbstractString, interpolate::Bool=true)
9294
update_arg(s[i:j-1]); i = k
9395
c, k = next(s,k)
9496
end
97+
elseif !in_single_quotes && !in_double_quotes && c in shell_special
98+
depwarn("special characters \"$shell_special\" should now be quoted in commands", :shell_parse)
9599
end
96100
j = k
97101
end
@@ -122,14 +126,14 @@ function shell_split(s::AbstractString)
122126
args
123127
end
124128

125-
function print_shell_word(io::IO, word::AbstractString)
129+
function print_shell_word(io::IO, word::AbstractString, special::AbstractString = shell_special)
126130
if isempty(word)
127131
print(io, "''")
128132
end
129133
has_single = false
130134
has_special = false
131135
for c in word
132-
if isspace(c) || c=='\\' || c=='\'' || c=='"' || c=='$'
136+
if isspace(c) || c=='\\' || c=='\'' || c=='"' || c=='$' || c in special
133137
has_special = true
134138
if c == '\''
135139
has_single = true
@@ -152,13 +156,17 @@ function print_shell_word(io::IO, word::AbstractString)
152156
end
153157
end
154158

155-
function print_shell_escaped(io::IO, cmd::AbstractString, args::AbstractString...)
156-
print_shell_word(io, cmd)
159+
function print_shell_escaped(
160+
io::IO, cmd::AbstractString, args::AbstractString...;
161+
special::AbstractString=shell_special
162+
)
163+
print_shell_word(io, cmd, special)
157164
for arg in args
158165
print(io, ' ')
159-
print_shell_word(io, arg)
166+
print_shell_word(io, arg, special)
160167
end
161168
end
162-
print_shell_escaped(io::IO) = nothing
169+
print_shell_escaped(io::IO; special::String=shell_special) = nothing
163170

164-
shell_escape(args::AbstractString...) = sprint(print_shell_escaped, args...)
171+
shell_escape(args::AbstractString...; special::AbstractString=shell_special) =
172+
sprint(io->print_shell_escaped(io, args..., special=special))

0 commit comments

Comments
 (0)