mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
harden alias
against foo; bar
If the first word of the alias body ends with a semicolon we need to strip that character, and otherwise escape the extracted command, to ensure the subsequent function definition is valid. Fixes #3860
This commit is contained in:
parent
992e1d0059
commit
9dd0c47d0b
4 changed files with 19 additions and 6 deletions
|
@ -11,6 +11,7 @@ function alias --description 'Creates a function wrapping a command'
|
||||||
set -l body
|
set -l body
|
||||||
set -l prefix
|
set -l prefix
|
||||||
set -l first_word
|
set -l first_word
|
||||||
|
set -l wrapped_cmd
|
||||||
switch (count $argv)
|
switch (count $argv)
|
||||||
|
|
||||||
case 0
|
case 0
|
||||||
|
@ -43,11 +44,13 @@ function alias --description 'Creates a function wrapping a command'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# Extract the first command from the body
|
# Extract the first command from the body. This is supposed to replace all non-escaped (i.e.
|
||||||
# This is supposed to replace all non-escaped (i.e. preceded by an odd number of `\`) spaces with a newline
|
# preceded by an odd number of `\`) spaces with a newline so it splits on them. See issue #2220
|
||||||
# so it splits on them
|
# for why the following borderline incomprehensible code exists.
|
||||||
set -l tmp (string replace -ra "([^\\\ ])((\\\\\\\)*) " '$1\n' $body)
|
set -l tmp (string replace -ra "([^\\\ ])((\\\\\\\)*) " '$1\n' $body)
|
||||||
set first_word (string trim $tmp[1])
|
set first_word (string trim $tmp[1])
|
||||||
|
# If the user does something like `alias x 'foo; bar'` we need to strip the semicolon.
|
||||||
|
set wrapped_cmd (string trim -c ';' $first_word)
|
||||||
if set -q tmp[2]
|
if set -q tmp[2]
|
||||||
set body $tmp[2..-1]
|
set body $tmp[2..-1]
|
||||||
else
|
else
|
||||||
|
@ -56,8 +59,7 @@ function alias --description 'Creates a function wrapping a command'
|
||||||
|
|
||||||
# Prevent the alias from immediately running into an infinite recursion if
|
# Prevent the alias from immediately running into an infinite recursion if
|
||||||
# $body starts with the same command as $name.
|
# $body starts with the same command as $name.
|
||||||
|
if test $wrapped_cmd = $name
|
||||||
if test $first_word = $name
|
|
||||||
if contains $name (builtin --names)
|
if contains $name (builtin --names)
|
||||||
set prefix builtin
|
set prefix builtin
|
||||||
else
|
else
|
||||||
|
@ -65,5 +67,7 @@ function alias --description 'Creates a function wrapping a command'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set -l cmd_string (string escape "alias $argv")
|
set -l cmd_string (string escape "alias $argv")
|
||||||
echo "function $name --wraps $first_word --description $cmd_string; $prefix $first_word $body \$argv; end" | source
|
set wrapped_cmd (string escape $wrapped_cmd)
|
||||||
|
echo "function $name --wraps $wrapped_cmd --description $cmd_string; $prefix $first_word $body \$argv; end" | source
|
||||||
|
#echo "function $name --wraps $wrapped_cmd --description $cmd_string; $prefix $first_word $body \$argv; end"
|
||||||
end
|
end
|
||||||
|
|
0
tests/alias.err
Normal file
0
tests/alias.err
Normal file
7
tests/alias.in
Normal file
7
tests/alias.in
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Avoid regressions of issue #3860 wherein the first word of the alias ends
|
||||||
|
# with a semicolon.
|
||||||
|
function foo
|
||||||
|
echo ran foo
|
||||||
|
end
|
||||||
|
alias my_alias "foo; and echo foo ran"
|
||||||
|
my_alias
|
2
tests/alias.out
Normal file
2
tests/alias.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ran foo
|
||||||
|
foo ran
|
Loading…
Reference in a new issue