git-gui: override exec and open only on Windows

Since aae9560a35 (Work around Tcl's default `PATH` lookup,
2022-11-23), git-gui overrides exec and open on all platforms. But,
this was done in response to Tcl adding elements to $PATH on Windows,
while exec, open, and auto_execok honor $PATH as given on all other
platforms.

Let's do the override only on Windows, restoring others to using their
native exec and open. These honor the sanitized $PATH as that is written
out to env(PATH) in a previous commit. auto_execok is also safe on these
platforms, so can be used for _which.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>

Signed-off-by: Taylor Blau <me@ttaylorr.com>
This commit is contained in:
Mark Levedahl
2025-04-11 10:58:20 -04:00
committed by Taylor Blau
parent 384b1409e8
commit a1ccd25120

View File

@@ -112,81 +112,91 @@ unset _path_seen
set env(PATH) [join $_search_path $_path_sep]
proc _which {what args} {
global _search_exe _search_path
if {[is_Windows]} {
proc _which {what args} {
global _search_exe _search_path
if {[is_Windows] && [lsearch -exact $args -script] >= 0} {
set suffix {}
} elseif {[is_Windows] && [string match *$_search_exe [string tolower $what]]} {
# The search string already has the file extension
set suffix {}
} else {
set suffix $_search_exe
}
foreach p $_search_path {
set p [file join $p $what$suffix]
if {[file exists $p]} {
return [file normalize $p]
if {[lsearch -exact $args -script] >= 0} {
set suffix {}
} elseif {[string match *$_search_exe [string tolower $what]]} {
# The search string already has the file extension
set suffix {}
} else {
set suffix $_search_exe
}
}
return {}
}
proc sanitize_command_line {command_line from_index} {
set i $from_index
while {$i < [llength $command_line]} {
set cmd [lindex $command_line $i]
if {[llength [file split $cmd]] < 2} {
set fullpath [_which $cmd]
if {$fullpath eq ""} {
throw {NOT-FOUND} "$cmd not found in PATH"
foreach p $_search_path {
set p [file join $p $what$suffix]
if {[file exists $p]} {
return [file normalize $p]
}
lset command_line $i $fullpath
}
return {}
}
# handle piped commands, e.g. `exec A | B`
for {incr i} {$i < [llength $command_line]} {incr i} {
if {[lindex $command_line $i] eq "|"} {
proc sanitize_command_line {command_line from_index} {
set i $from_index
while {$i < [llength $command_line]} {
set cmd [lindex $command_line $i]
if {[llength [file split $cmd]] < 2} {
set fullpath [_which $cmd]
if {$fullpath eq ""} {
throw {NOT-FOUND} "$cmd not found in PATH"
}
lset command_line $i $fullpath
}
# handle piped commands, e.g. `exec A | B`
for {incr i} {$i < [llength $command_line]} {incr i} {
if {[lindex $command_line $i] eq "|"} {
incr i
break
}
}
}
return $command_line
}
# Override `exec` to avoid unsafe PATH lookup
rename exec real_exec
proc exec {args} {
# skip options
for {set i 0} {$i < [llength $args]} {incr i} {
set arg [lindex $args $i]
if {$arg eq "--"} {
incr i
break
}
if {[string range $arg 0 0] ne "-"} {
break
}
}
set args [sanitize_command_line $args $i]
uplevel 1 real_exec $args
}
return $command_line
}
# Override `exec` to avoid unsafe PATH lookup
# Override `open` to avoid unsafe PATH lookup
rename exec real_exec
rename open real_open
proc exec {args} {
# skip options
for {set i 0} {$i < [llength $args]} {incr i} {
set arg [lindex $args $i]
if {$arg eq "--"} {
incr i
break
}
if {[string range $arg 0 0] ne "-"} {
break
proc open {args} {
set arg0 [lindex $args 0]
if {[string range $arg0 0 0] eq "|"} {
set command_line [string trim [string range $arg0 1 end]]
lset args 0 "| [sanitize_command_line $command_line 0]"
}
uplevel 1 real_open $args
}
set args [sanitize_command_line $args $i]
uplevel 1 real_exec $args
}
# Override `open` to avoid unsafe PATH lookup
} else {
# On non-Windows platforms, auto_execok, exec, and open are safe, and will
# use the sanitized search path. But, we need _which for these.
rename open real_open
proc open {args} {
set arg0 [lindex $args 0]
if {[string range $arg0 0 0] eq "|"} {
set command_line [string trim [string range $arg0 1 end]]
lset args 0 "| [sanitize_command_line $command_line 0]"
proc _which {what args} {
return [lindex [auto_execok $what] 0]
}
uplevel 1 real_open $args
}
######################################################################