Skip to content

Commit fe32bf3

Browse files
j6tttaylorr
authored andcommitted
gitk: sanitize 'open' arguments: simple commands
Tcl 'open' treats the second argument as a command when it begins with |. The remainder of the argument is a list comprising the command and its arguments. It assigns special meaning to these arguments when they begin with a redirection, pipe or background operator. There are a number of invocations of 'open' 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 which have these special forms. They must not be interpreted by 'open' 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. Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent 30846b4 commit fe32bf3

File tree

1 file changed

+33
-26
lines changed

1 file changed

+33
-26
lines changed

gitk

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ proc safe_open_file {filename flags} {
5959
open $filename $flags
6060
}
6161

62+
# opens a command pipeline for reading
63+
# cmd is a list that specifies the command and its arguments
64+
# calls `open` and returns the file id
65+
proc safe_open_command {cmd} {
66+
open |[make_arglist_safe $cmd] r
67+
}
68+
6269
# End exec/open wrappers
6370

6471
proc hasworktree {} {
@@ -186,7 +193,7 @@ proc unmerged_files {files} {
186193
set mlist {}
187194
set nr_unmerged 0
188195
if {[catch {
189-
set fd [open "| git ls-files -u" r]
196+
set fd [safe_open_command {git ls-files -u}]
190197
} err]} {
191198
show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
192199
exit 1
@@ -463,8 +470,8 @@ proc start_rev_list {view} {
463470
}
464471

465472
if {[catch {
466-
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
467-
--parents --boundary $args "--" $files] r]
473+
set fd [safe_open_command [concat git log --no-color -z --pretty=raw $show_notes \
474+
--parents --boundary $args "--" $files]]
468475
} err]} {
469476
error_popup "[mc "Error executing git log:"] $err"
470477
return 0
@@ -611,8 +618,8 @@ proc updatecommits {} {
611618
set args $vorigargs($view)
612619
}
613620
if {[catch {
614-
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
615-
--parents --boundary $args "--" $vfilelimit($view)] r]
621+
set fd [safe_open_command [concat git log --no-color -z --pretty=raw $show_notes \
622+
--parents --boundary $args "--" $vfilelimit($view)]]
616623
} err]} {
617624
error_popup "[mc "Error executing git log:"] $err"
618625
return
@@ -1700,7 +1707,7 @@ proc do_readcommit {id} {
17001707
global tclencoding
17011708

17021709
# Invoke git-log to handle automatic encoding conversion
1703-
set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1710+
set fd [safe_open_command [concat git log --no-color --pretty=raw -1 $id]]
17041711
# Read the results using i18n.logoutputencoding
17051712
fconfigure $fd -translation lf -eofchar {}
17061713
if {$tclencoding != {}} {
@@ -1836,7 +1843,7 @@ proc readrefs {} {
18361843
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
18371844
unset -nocomplain $v
18381845
}
1839-
set refd [open [list | git show-ref -d] r]
1846+
set refd [safe_open_command [list git show-ref -d]]
18401847
if {$tclencoding != {}} {
18411848
fconfigure $refd -encoding $tclencoding
18421849
}
@@ -3729,7 +3736,7 @@ proc external_diff {} {
37293736

37303737
if {$difffromfile ne {} && $difftofile ne {}} {
37313738
set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3732-
if {[catch {set fl [open |$cmd r]} err]} {
3739+
if {[catch {set fl [safe_open_command $cmd]} err]} {
37333740
file delete -force $diffdir
37343741
error_popup "$extdifftool: [mc "command failed:"] $err"
37353742
} else {
@@ -3833,7 +3840,7 @@ proc external_blame_diff {} {
38333840
# Find the SHA1 ID of the blob for file $fname in the index
38343841
# at stage 0 or 2
38353842
proc index_sha1 {fname} {
3836-
set f [open [list | git ls-files -s $fname] r]
3843+
set f [safe_open_command [list git ls-files -s $fname]]
38373844
while {[gets $f line] >= 0} {
38383845
set info [lindex [split $line "\t"] 0]
38393846
set stage [lindex $info 2]
@@ -5311,8 +5318,8 @@ proc get_viewmainhead {view} {
53115318
global viewmainheadid vfilelimit viewinstances mainheadid
53125319

53135320
catch {
5314-
set rfd [open [concat | git rev-list -1 $mainheadid \
5315-
-- $vfilelimit($view)] r]
5321+
set rfd [safe_open_command [concat git rev-list -1 $mainheadid \
5322+
-- $vfilelimit($view)]]
53165323
set j [reg_instance $rfd]
53175324
lappend viewinstances($view) $j
53185325
fconfigure $rfd -blocking 0
@@ -5377,14 +5384,14 @@ proc dodiffindex {} {
53775384
if {!$showlocalchanges || !$hasworktree} return
53785385
incr lserial
53795386
if {[package vcompare $git_version "1.7.2"] >= 0} {
5380-
set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5387+
set cmd "git diff-index --cached --ignore-submodules=dirty HEAD"
53815388
} else {
5382-
set cmd "|git diff-index --cached HEAD"
5389+
set cmd "git diff-index --cached HEAD"
53835390
}
53845391
if {$vfilelimit($curview) ne {}} {
53855392
set cmd [concat $cmd -- $vfilelimit($curview)]
53865393
}
5387-
set fd [open $cmd r]
5394+
set fd [safe_open_command $cmd]
53885395
fconfigure $fd -blocking 0
53895396
set i [reg_instance $fd]
53905397
filerun $fd [list readdiffindex $fd $lserial $i]
@@ -5409,11 +5416,11 @@ proc readdiffindex {fd serial inst} {
54095416
}
54105417

54115418
# now see if there are any local changes not checked in to the index
5412-
set cmd "|git diff-files"
5419+
set cmd "git diff-files"
54135420
if {$vfilelimit($curview) ne {}} {
54145421
set cmd [concat $cmd -- $vfilelimit($curview)]
54155422
}
5416-
set fd [open $cmd r]
5423+
set fd [safe_open_command $cmd]
54175424
fconfigure $fd -blocking 0
54185425
set i [reg_instance $fd]
54195426
filerun $fd [list readdifffiles $fd $serial $i]
@@ -7705,13 +7712,13 @@ proc gettree {id} {
77057712
if {![info exists treefilelist($id)]} {
77067713
if {![info exists treepending]} {
77077714
if {$id eq $nullid} {
7708-
set cmd [list | git ls-files]
7715+
set cmd [list git ls-files]
77097716
} elseif {$id eq $nullid2} {
7710-
set cmd [list | git ls-files --stage -t]
7717+
set cmd [list git ls-files --stage -t]
77117718
} else {
7712-
set cmd [list | git ls-tree -r $id]
7719+
set cmd [list git ls-tree -r $id]
77137720
}
7714-
if {[catch {set gtf [open $cmd r]}]} {
7721+
if {[catch {set gtf [safe_open_command $cmd]}]} {
77157722
return
77167723
}
77177724
set treepending $id
@@ -7781,7 +7788,7 @@ proc showfile {f} {
77817788
}
77827789
} else {
77837790
set blob [lindex $treeidlist($diffids) $i]
7784-
if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7791+
if {[catch {set bf [safe_open_command [concat git cat-file blob $blob]]} err]} {
77857792
puts "oops, error reading blob $blob: $err"
77867793
return
77877794
}
@@ -7976,7 +7983,7 @@ proc gettreediffs {ids} {
79767983
if {$limitdiffs && $vfilelimit($curview) ne {}} {
79777984
set cmd [concat $cmd -- $vfilelimit($curview)]
79787985
}
7979-
if {[catch {set gdtf [open |$cmd r]}]} return
7986+
if {[catch {set gdtf [safe_open_command $cmd]}]} return
79807987

79817988
set treepending $ids
79827989
set treediff {}
@@ -8096,7 +8103,7 @@ proc getblobdiffs {ids} {
80968103
if {$limitdiffs && $vfilelimit($curview) ne {}} {
80978104
set cmd [concat $cmd -- $vfilelimit($curview)]
80988105
}
8099-
if {[catch {set bdf [open |$cmd r]} err]} {
8106+
if {[catch {set bdf [safe_open_command $cmd]} err]} {
81008107
error_popup [mc "Error getting diffs: %s" $err]
81018108
return
81028109
}
@@ -9223,7 +9230,7 @@ proc diffcommits {a b} {
92239230
return
92249231
}
92259232
if {[catch {
9226-
set fd [open "| diff -U$diffcontext $fna $fnb" r]
9233+
set fd [safe_open_command "diff -U$diffcontext $fna $fnb"]
92279234
} err]} {
92289235
error_popup [mc "Error diffing commits: %s" $err]
92299236
return
@@ -10256,7 +10263,7 @@ proc getallcommits {} {
1025610263
if {$allcwait} {
1025710264
return
1025810265
}
10259-
set cmd [list | git rev-list --parents]
10266+
set cmd [list git rev-list --parents]
1026010267
set allcupdate [expr {$seeds ne {}}]
1026110268
if {!$allcupdate} {
1026210269
set ids "--all"
@@ -10281,7 +10288,7 @@ proc getallcommits {} {
1028110288
}
1028210289
}
1028310290
if {$ids ne {}} {
10284-
set fd [open [concat $cmd $ids] r]
10291+
set fd [safe_open_command [concat $cmd $ids]]
1028510292
fconfigure $fd -blocking 0
1028610293
incr allcommits
1028710294
nowbusy allcommits

0 commit comments

Comments
 (0)