From: Taylor Blau Date: Fri, 23 May 2025 21:04:27 +0000 (-0400) Subject: Merge branch 'ml/replace-auto-execok' into js/fix-open-exec X-Git-Tag: v2.43.7~4^2^2~1 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=afca9a4fb4e3c8acbc464bca69cde5c7397c25e1;p=thirdparty%2Fgit.git Merge branch 'ml/replace-auto-execok' into js/fix-open-exec Signed-off-by: Taylor Blau --- afca9a4fb4e3c8acbc464bca69cde5c7397c25e1 diff --cc git-gui.sh index 9ad172ac66,21c3858d2e..0355c0c836 --- a/git-gui.sh +++ b/git-gui.sh @@@ -132,94 -169,36 +169,86 @@@ if {[is_Windows]} 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 - - rename open real_open + } 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. - 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 } +# Wrap exec/open to sanitize arguments + +# unsafe arguments begin with redirections or the pipe or background operators +proc is_arg_unsafe {arg} { + regexp {^([<|>&]|2>)} $arg +} + +proc make_arg_safe {arg} { + if {[is_arg_unsafe $arg]} { + set arg [file join . $arg] + } + return $arg +} + +proc make_arglist_safe {arglist} { + set res {} + foreach arg $arglist { + lappend res [make_arg_safe $arg] + } + return $res +} + +# executes one command +# no redirections or pipelines are possible +# cmd is a list that specifies the command and its arguments +# calls `exec` and returns its value +proc safe_exec {cmd} { + eval exec [make_arglist_safe $cmd] +} + +# executes one command in the background +# no redirections or pipelines are possible +# cmd is a list that specifies the command and its arguments +# calls `exec` and returns its value +proc safe_exec_bg {cmd} { + eval exec [make_arglist_safe $cmd] & +} + +proc safe_open_file {filename flags} { + # a file name starting with "|" would attempt to run a process + # but such a file name must be treated as a relative path + # hide the "|" behind "./" + if {[string index $filename 0] eq "|"} { + set filename [file join . $filename] + } + open $filename $flags +} + +# End exec/open wrappers + ###################################################################### ## ## locate our library @@@ -574,33 -575,13 +625,14 @@@ proc _git_cmd {name} return $v } - # Test a file for a hashbang to identify executable scripts on Windows. - proc is_shellscript {filename} { - if {![file exists $filename]} {return 0} - set f [safe_open_file $filename r] - fconfigure $f -encoding binary - set magic [read $f 2] - close $f - return [expr {$magic eq "#!"}] - } - - # Run a command connected via pipes on stdout. + # Run a shell command connected via pipes on stdout. # This is for use with textconv filters and uses sh -c "..." to allow it to - # contain a command with arguments. On windows we must check for shell - # scripts specifically otherwise just call the filter command. + # contain a command with arguments. We presume this + # to be a shellscript that the configured shell (/bin/sh by default) knows + # how to run. proc open_cmd_pipe {cmd path} { - global env - if {![file executable [shellpath]]} { - set exe [auto_execok [lindex $cmd 0]] - if {[is_shellscript [lindex $exe 0]]} { - set run [linsert [auto_execok sh] end -c "$cmd \"\$0\"" $path] - } else { - set run [concat $exe [lrange $cmd 1 end] $path] - } - } else { - set run [list [shellpath] -c "$cmd \"\$0\"" $path] - } + set run [list [shellpath] -c "$cmd \"\$0\"" $path] + set run [make_arglist_safe $run] return [open |$run r] } @@@ -2746,17 -2785,16 +2778,16 @@@ if {![is_bare]} if {[is_Windows]} { # Use /git-bash.exe if available - set normalized [file normalize $::argv0] - regsub "/mingw../libexec/git-core/git-gui$" \ - $normalized "/git-bash.exe" cmdLine - if {$cmdLine != $normalized && [file exists $cmdLine]} { - set cmdLine [list "Git Bash" $cmdLine] + set _git_bash [exec cygpath -m /git-bash.exe] + if {[file executable $_git_bash]} { - set _bash_cmdline [list "Git Bash" $_git_bash &] ++ set _bash_cmdline [list "Git Bash" $_git_bash] } else { - set cmdLine [list "Git Bash" bash --login -l] - set _bash_cmdline [list "Git Bash" bash --login -l &] ++ set _bash_cmdline [list "Git Bash" bash --login -l] } .mbar.repository add command \ -label [mc "Git Bash"] \ - -command {safe_exec_bg [concat [list [auto_execok start]] $cmdLine]} - -command {eval exec [list [_which cmd] /c start] $_bash_cmdline} ++ -command {safe_exec_bg [concat [list [_which cmd] /c start] $_bash_cmdline]} + unset _git_bash } if {[is_Windows] || ![is_bare]} { diff --cc lib/sshkey.tcl index b32bdd06e9,c0c5d1dad8..c3e681b899 --- a/lib/sshkey.tcl +++ b/lib/sshkey.tcl @@@ -83,9 -83,10 +83,10 @@@ proc make_ssh_key {w} set sshkey_title [mc "Generating..."] $w.header.gen configure -state disabled - set cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}] + set cmdline [list [shellpath] -c \ + {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}] - if {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} { + if {[catch { set sshkey_fd [safe_open_command $cmdline] } err]} { error_popup [mc "Could not start ssh-keygen:\n\n%s" $err] return }