gitk: treat file names beginning with "|" as relative paths
The Tcl 'open' function has a vary wide interface. It can open files as well as pipes to external processes. The difference is made only by the first character of the file name: if it is "|", an process is spawned. We have a number of calls of Tcl 'open' that take a file name from the environment in which Gitk is running. Be prepared that insane values are injected. In particular, when we intend to open a file, do not mistake a file name that happens to begin with "|" as a request to run a process. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Taylor Blau <me@ttaylorr.com>
Johannes Sixt committed
Mar 17, 2025 at 20:36 UTC
b966b738e1923badc788b9111cc81653b50ff164
1 file changed
+18
-5
gitk
+18
-5
@@ -9,6 +9,19 @@ exec wish "$0" -- "$@"
9
10
package require Tk
11
12
+
13
+# Wrap open to sanitize arguments
14
+
15
+proc safe_open_file {filename flags} {
16
+ # a file name starting with "|" would attempt to run a process
17
+ # but such a file name must be treated as a relative path
18
+ # hide the "|" behind "./"
19
+ if {[string index $filename 0] eq "|"} {
20
+ set filename [file join . $filename]
21
+ }
22
+ open $filename $flags
23
+}
24
+
25
proc hasworktree {} {
26
return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
27
[exec git rev-parse --is-inside-git-dir] == "false"}]
@@ -2874,7 +2887,7 @@ proc savestuff {w} {
2887
set remove_tmp 0
2888
if {[catch {
2889
set try_count 0
2877
- while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2890
+ while {[catch {set f [safe_open_file $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2891
if {[incr try_count] > 50} {
2892
error "Unable to write config file: $config_file_tmp exists"
2893
}
@@ -3869,7 +3882,7 @@ proc show_line_source {} {
3882
# must be a merge in progress...
3883
if {[catch {
3884
# get the last line from .git/MERGE_HEAD
3872
- set f [open [file join $gitdir MERGE_HEAD] r]
3885
+ set f [safe_open_file [file join $gitdir MERGE_HEAD] r]
3886
set id [lindex [split [read $f] "\n"] end-1]
3887
close $f
3888
} err]} {
@@ -7723,7 +7736,7 @@ proc showfile {f} {
7736
return
7737
}
7738
if {$diffids eq $nullid} {
7726
- if {[catch {set bf [open $f r]} err]} {
7739
+ if {[catch {set bf [safe_open_file $f r]} err]} {
7740
puts "oops, can't read $f: $err"
7741
return
7742
}
@@ -10200,7 +10213,7 @@ proc getallcommits {} {
10213
set cachedarcs 0
10214
set allccache [file join $gitdir "gitk.cache"]
10215
if {![catch {
10203
- set f [open $allccache r]
10216
+ set f [safe_open_file $allccache r]
10217
set allcwait 1
10218
getcache $f
10219
}]} return
@@ -10624,7 +10637,7 @@ proc savecache {} {
10637
set cachearc 0
10638
set cachedarcs $nextarc
10639
catch {
10627
- set f [open $allccache w]
10640
+ set f [safe_open_file $allccache w]
10641
puts $f [list 1 $cachedarcs]
10642
run writecache $f
10643
}