Skip to content

Commit 4f3e0a4

Browse files
j6tttaylorr
authored andcommitted
git-gui: sanitize 'exec' arguments: simple cases
Tcl 'exec' assigns special meaning to its argument when they begin with redirection, pipe or background operator. There are a number of invocations of 'exec' which construct arguments that are taken from the Git repository or a user input. However, when file names or ref names are taken from the repository, it is possible to find names that have these special forms. They must not be interpreted by 'exec' lest it redirects input or output, or attempts to build a pipeline using a command name controlled by the repository. Introduce a helper function that identifies such arguments and prepends "./" to force such a name to be regarded as a relative file name. Convert those 'exec' calls where the arguments can simply be packed into a list. Note that most commands containing the word 'exec' route through console::exec or console::chain, which we will treat in another commit. Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent c2e8904 commit 4f3e0a4

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

git-gui.sh

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,35 @@ proc open {args} {
170170
uplevel 1 real_open $args
171171
}
172172
173-
# Wrap open to sanitize arguments
173+
# Wrap exec/open to sanitize arguments
174+
175+
# unsafe arguments begin with redirections or the pipe or background operators
176+
proc is_arg_unsafe {arg} {
177+
regexp {^([<|>&]|2>)} $arg
178+
}
179+
180+
proc make_arg_safe {arg} {
181+
if {[is_arg_unsafe $arg]} {
182+
set arg [file join . $arg]
183+
}
184+
return $arg
185+
}
186+
187+
proc make_arglist_safe {arglist} {
188+
set res {}
189+
foreach arg $arglist {
190+
lappend res [make_arg_safe $arg]
191+
}
192+
return $res
193+
}
194+
195+
# executes one command
196+
# no redirections or pipelines are possible
197+
# cmd is a list that specifies the command and its arguments
198+
# calls `exec` and returns its value
199+
proc safe_exec {cmd} {
200+
eval exec [make_arglist_safe $cmd]
201+
}
174202
175203
proc safe_open_file {filename flags} {
176204
# a file name starting with "|" would attempt to run a process
@@ -182,6 +210,8 @@ proc safe_open_file {filename flags} {
182210
open $filename $flags
183211
}
184212
213+
# End exec/open wrappers
214+
185215
######################################################################
186216
##
187217
## locate our library
@@ -282,11 +312,11 @@ unset oguimsg
282312
283313
if {[tk windowingsystem] eq "aqua"} {
284314
catch {
285-
exec osascript -e [format {
315+
safe_exec [list osascript -e [format {
286316
tell application "System Events"
287317
set frontmost of processes whose unix id is %d to true
288318
end tell
289-
} [pid]]
319+
} [pid]]]
290320
}
291321
}
292322
@@ -571,7 +601,7 @@ proc _lappend_nice {cmd_var} {
571601

572602
if {![info exists _nice]} {
573603
set _nice [_which nice]
574-
if {[catch {exec $_nice git version}]} {
604+
if {[catch {safe_exec [list $_nice git version]}]} {
575605
set _nice {}
576606
} elseif {[is_Windows] && [file dirname $_nice] ne [file dirname $::_git]} {
577607
set _nice {}
@@ -667,9 +697,9 @@ proc kill_file_process {fd} {
667697

668698
catch {
669699
if {[is_Windows]} {
670-
exec taskkill /pid $process
700+
safe_exec [list taskkill /pid $process]
671701
} else {
672-
exec kill $process
702+
safe_exec [list kill $process]
673703
}
674704
}
675705
}

lib/diff.tcl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ proc show_other_diff {path w m cont_info} {
226226
$ui_diff insert end \
227227
"* [mc "Git Repository (subproject)"]\n" \
228228
d_info
229-
} elseif {![catch {set type [exec file $path]}]} {
229+
} elseif {![catch {set type [safe_exec [list file $path]]}]} {
230230
set n [string length $path]
231231
if {[string equal -length $n $path $type]} {
232232
set type [string range $type $n end]

lib/shortcut.tcl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ proc do_cygwin_shortcut {} {
3030
global argv0 _gitworktree oguilib
3131

3232
if {[catch {
33-
set desktop [exec cygpath \
34-
--desktop]
33+
set desktop [safe_exec [list cygpath \
34+
--desktop]]
3535
}]} {
3636
set desktop .
3737
}
@@ -50,14 +50,14 @@ proc do_cygwin_shortcut {} {
5050
"CHERE_INVOKING=1 \
5151
source /etc/profile; \
5252
git gui"}
53-
exec /bin/mkshortcut.exe \
53+
safe_exec [list /bin/mkshortcut.exe \
5454
--arguments $shargs \
5555
--desc "git-gui on $repodir" \
5656
--icon $oguilib/git-gui.ico \
5757
--name $fn \
5858
--show min \
5959
--workingdir $repodir \
60-
/bin/sh.exe
60+
/bin/sh.exe]
6161
} err]} {
6262
error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]
6363
}

lib/win32.tcl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# Copyright (C) 2007 Shawn Pearce
33

44
proc win32_read_lnk {lnk_path} {
5-
return [exec cscript.exe \
5+
return [safe_exec [list cscript.exe \
66
/E:jscript \
77
/nologo \
88
[file join $::oguilib win32_shortcut.js] \
9-
$lnk_path]
9+
$lnk_path]]
1010
}
1111

1212
proc win32_create_lnk {lnk_path lnk_exec lnk_dir} {
@@ -15,12 +15,13 @@ proc win32_create_lnk {lnk_path lnk_exec lnk_dir} {
1515
set lnk_args [lrange $lnk_exec 1 end]
1616
set lnk_exec [lindex $lnk_exec 0]
1717

18-
eval [list exec wscript.exe \
18+
set cmd [list wscript.exe \
1919
/E:jscript \
2020
/nologo \
2121
[file nativename [file join $oguilib win32_shortcut.js]] \
2222
$lnk_path \
2323
[file nativename [file join $oguilib git-gui.ico]] \
2424
$lnk_dir \
25-
$lnk_exec] $lnk_args
25+
$lnk_exec]
26+
safe_exec [concat $cmd $lnk_args]
2627
}

0 commit comments

Comments
 (0)