diff options
author | Junio C Hamano <gitster@pobox.com> | 2014-05-20 03:10:10 +0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-05-20 03:10:10 +0400 |
commit | df43b41afcc9bf5e4b8751dc9a53b068b33f52a8 (patch) | |
tree | d4cfa3e6743445805364bbe13fa36138a48e4185 /contrib/completion/git-prompt.sh | |
parent | 7dde48ea7aa18de1174628e21510967b0ad71d7c (diff) | |
parent | 1e4119c81b3e203e1729e03be6e4a53eb9207f5c (diff) |
Merge branch 'rh/prompt-pcmode-avoid-eval-on-refname'
* rh/prompt-pcmode-avoid-eval-on-refname:
git-prompt.sh: don't assume the shell expands the value of PS1
Diffstat (limited to 'contrib/completion/git-prompt.sh')
-rw-r--r-- | contrib/completion/git-prompt.sh | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 853425d005..9d684b10a6 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -209,9 +209,7 @@ __git_ps1_show_upstream () if [[ -n "$count" && -n "$name" ]]; then __git_ps1_upstream_name=$(git rev-parse \ --abbrev-ref "$upstream" 2>/dev/null) - if [ $pcmode = yes ]; then - # see the comments around the - # __git_ps1_branch_name variable below + if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then p="$p \${__git_ps1_upstream_name}" else p="$p ${__git_ps1_upstream_name}" @@ -308,6 +306,43 @@ __git_ps1 () ;; esac + # ps1_expanded: This variable is set to 'yes' if the shell + # subjects the value of PS1 to parameter expansion: + # + # * bash does unless the promptvars option is disabled + # * zsh does not unless the PROMPT_SUBST option is set + # * POSIX shells always do + # + # If the shell would expand the contents of PS1 when drawing + # the prompt, a raw ref name must not be included in PS1. + # This protects the user from arbitrary code execution via + # specially crafted ref names. For example, a ref named + # 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the + # shell to execute 'sudo rm -rf /' when the prompt is drawn. + # + # Instead, the ref name should be placed in a separate global + # variable (in the __git_ps1_* namespace to avoid colliding + # with the user's environment) and that variable should be + # referenced from PS1. For example: + # + # __git_ps1_foo=$(do_something_to_get_ref_name) + # PS1="...stuff...\${__git_ps1_foo}...stuff..." + # + # If the shell does not expand the contents of PS1, the raw + # ref name must be included in PS1. + # + # The value of this variable is only relevant when in pcmode. + # + # Assume that the shell follows the POSIX specification and + # expands PS1 unless determined otherwise. (This is more + # likely to be correct if the user has a non-bash, non-zsh + # shell and safer than the alternative if the assumption is + # incorrect.) + # + local ps1_expanded=yes + [ -z "$ZSH_VERSION" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no + [ -z "$BASH_VERSION" ] || shopt -q promptvars || ps1_expanded=no + local repo_info rev_parse_exit_code repo_info="$(git rev-parse --git-dir --is-inside-git-dir \ --is-bare-repository --is-inside-work-tree \ @@ -457,21 +492,8 @@ __git_ps1 () fi b=${b##refs/heads/} - if [ $pcmode = yes ]; then - # In pcmode (and only pcmode) the contents of - # $gitstring are subject to expansion by the shell. - # Avoid putting the raw ref name in the prompt to - # protect the user from arbitrary code execution via - # specially crafted ref names (e.g., a ref named - # '$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' would execute - # 'sudo rm -rf /' when the prompt is drawn). Instead, - # put the ref name in a new global variable (in the - # __git_ps1_* namespace to avoid colliding with the - # user's environment) and reference that variable from - # PS1. + if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then __git_ps1_branch_name=$b - # note that the $ is escaped -- the variable will be - # expanded later (when it's time to draw the prompt) b="\${__git_ps1_branch_name}" fi |