[Toybox] Shell corner cases.
Rob Landley
rob at landley.net
Wed Apr 30 15:23:54 PDT 2025
On 4/29/25 08:53, Chet Ramey wrote:
> On 4/28/25 6:03 PM, Rob Landley wrote:
>> FYI, I'd prefer not to implement either of these in toybox:
>>
>> 1) function names with / in them
>>
>> $ which sudo
>> /usr/bin/sudo
>> $ /usr/bin/sudo() { echo owned; }
>> $ /usr/bin/sudo
>> owned
>> $ ./sudo() { echo still owned; }
>> $ ./sudo
>> still owned
>
> Sure, probably a good idea. POSIX execution rules say they'd never be
> called anyway.
Somebody forwarded that to me from an exploit how-to site. It's
apparently a trick used to subvert scripts that call things via absolute
path to avoid malicious $PATH.
>> 2) deferred alias definitions
>>
>> $ alias potato='echo hello'; potato
>> bash: potato: command not found
>> $ potato
>> hello
>
> I'm not sure what `deferred' means here. The shell reads a line of input,
> parses it into a command (a list with two elements in this case), then
> executes the command.
$ x() { echo hello; }; D=x; $D
hello
> Since alias expansion happens when the command is
> read and tokenized,
Yeah, that was the weird part. My code breaks argv[] into separate
chunks but doesn't try to figure out what they _mean_ until it needs to
run them, because:
$ alias one='$X'
$ X='$A'; A=$X one
bash: $A: command not found
Is still figuring out that it has to move past the prefix assignment to
expand the alias, so you're saying your "tokenization" recognizes prefix
assignments...
> the list will be parsed before any of the commands
> are executed. This is how Bourne-style shells work.
The logic of what counts as a "line" in this context is unclear to me:
$ bash -c $'echo $LINENO;alias a=b\necho $LINENO;a'
1
2
bash: line 2: a: command not found
It's the second line according to $LINENO but the same one according to
alias tokenization. That really seems like an implementation detail
bubbling through. I was just treating aliases as early functions sniped
before variable expansion, so:
$ alias one=ls ;B=one
$ $B
bash: one: command not found
Wouldn't trigger (like it does for functions).
Then again busybox ash, mksh, zsh, and even dash are all doing this too,
so I guess "compatible" beats "sane". Maybe it's so you can do:
alias potato=fruitbat
source filename
unalias potato
And, of course:
$ alias one=two
$ on\e
bash: one: command not found
So many corner cases to test...
Rob
More information about the Toybox
mailing list