Fix BUG_CASELIT: pattern matching as literal string in 'case'
This fixes an undocumented 'case' pattern matching misbehaviour
(labelled BUG_CASELIT in modernish) that goes back to the original
Bourne shell, but wasn't discovered until 2018.
If a pattern doesn't match as a pattern, it's tried again as a
literal string. This breaks common validation use cases, such as:
n='[0-9]'
case $n in
( [0-9] ) echo "$n is a number" ;;
esac
would output "[0-9] is a number" as the literal string fallback
matches the pattern. As this misbehaviour was never documented
anywhere (not for Bourne, ksh88, or ksh93), and it was never
replicated in other shells (not even in ksh88 clones pdksh and
mksh), it is unlikely any scripts rely on it.
Of course, a literal string fallback, should it be needed, is
trivial to implement correctly without this breakage:
case $n in
( [0-9] | "[0-9]") echo "$n is a number or the number pattern" ;;
esac
src/cmd/ksh93/sh/xec.c:
- Remove trim_eq() function responsible for implementing the
misbehaviour described above.
NEWS:
- Added. Document this bugfix.
Ref.:
- The problem: thread starting at
https://www.mail-archive.com/austin-group-l@opengroup.org/msg02127.html
- The solution, thanks to George Koehler: comments/commits in
https://github.com/att/ast/issues/476
- Modernish BUG_CASELIT bug test & documentation:
https://github.com/modernish/modernish/commit/b2024ae3
(cherry picked from commit 8d6c8ce69884767a160c1e20049e77bdd849c248
with some extra edits to NEWS to upate the info for this reboot)
2020-06-11 15:14:31 +00:00
|
|
|
This documents significant changes in the 93u+m branch of AT&T ksh93.
|
2020-06-14 04:28:38 +00:00
|
|
|
For full details, see the git log at: https://github.com/ksh93/ksh
|
Fix BUG_CASELIT: pattern matching as literal string in 'case'
This fixes an undocumented 'case' pattern matching misbehaviour
(labelled BUG_CASELIT in modernish) that goes back to the original
Bourne shell, but wasn't discovered until 2018.
If a pattern doesn't match as a pattern, it's tried again as a
literal string. This breaks common validation use cases, such as:
n='[0-9]'
case $n in
( [0-9] ) echo "$n is a number" ;;
esac
would output "[0-9] is a number" as the literal string fallback
matches the pattern. As this misbehaviour was never documented
anywhere (not for Bourne, ksh88, or ksh93), and it was never
replicated in other shells (not even in ksh88 clones pdksh and
mksh), it is unlikely any scripts rely on it.
Of course, a literal string fallback, should it be needed, is
trivial to implement correctly without this breakage:
case $n in
( [0-9] | "[0-9]") echo "$n is a number or the number pattern" ;;
esac
src/cmd/ksh93/sh/xec.c:
- Remove trim_eq() function responsible for implementing the
misbehaviour described above.
NEWS:
- Added. Document this bugfix.
Ref.:
- The problem: thread starting at
https://www.mail-archive.com/austin-group-l@opengroup.org/msg02127.html
- The solution, thanks to George Koehler: comments/commits in
https://github.com/att/ast/issues/476
- Modernish BUG_CASELIT bug test & documentation:
https://github.com/modernish/modernish/commit/b2024ae3
(cherry picked from commit 8d6c8ce69884767a160c1e20049e77bdd849c248
with some extra edits to NEWS to upate the info for this reboot)
2020-06-11 15:14:31 +00:00
|
|
|
|
|
|
|
Any uppercase BUG_* names are modernish shell bug IDs.
|
|
|
|
|
2020-06-16 11:21:42 +00:00
|
|
|
2020-06-16:
|
|
|
|
|
|
|
|
- Passing the '-d' flag to the read builtin will no longer cause the '-r'
|
|
|
|
flag to be discarded when 'read -r -d' is run.
|
|
|
|
|
2020-06-16 21:58:05 +00:00
|
|
|
- Fix BUG_CMDSPASGN: preceding a "special builtin"[*] with 'command' now
|
|
|
|
prevents preceding invocation-local variable assignments from becoming global.
|
|
|
|
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
|
|
|
|
|
2020-06-15 07:03:44 +00:00
|
|
|
2020-06-15:
|
|
|
|
|
|
|
|
- The 'source' alias has been converted into a regular built-in command.
|
|
|
|
|
2020-06-15 13:43:37 +00:00
|
|
|
- Functions that set variables in a virtual subshell will no longer affect
|
|
|
|
variables of the same name outside of the virtual subshell's environment.
|
|
|
|
|
2020-06-15 14:56:11 +00:00
|
|
|
- Terse usage messages written by builtin commands now point the user to
|
|
|
|
the --help and --man options for more information.
|
|
|
|
|
2020-06-14 16:28:22 +00:00
|
|
|
2020-06-14:
|
2020-06-15 07:03:44 +00:00
|
|
|
|
2020-06-14 16:28:22 +00:00
|
|
|
- 'read -S' is now able to correctly handle strings with double quotes
|
|
|
|
nested inside of double quotes.
|
|
|
|
|
2020-06-13 21:16:08 +00:00
|
|
|
2020-06-13:
|
2020-06-14 04:28:38 +00:00
|
|
|
|
2020-06-13 21:16:08 +00:00
|
|
|
- Fixed a timezone name determination bug on FreeBSD that caused the
|
|
|
|
output from `LC_ALL=C printf '%T' now` to print the wrong time zone name.
|
|
|
|
|
2020-06-11 10:43:17 +00:00
|
|
|
2020-06-11:
|
|
|
|
|
2020-06-12 03:18:01 +00:00
|
|
|
- Fixed a bug that caused running 'builtin -d' on a special builtin to
|
|
|
|
delete it. The man page for the 'builtin' command documents that special
|
|
|
|
builtins cannot be deleted.
|
|
|
|
|
2020-06-11 10:43:17 +00:00
|
|
|
- POSIX compliance fix: It is now possible to set shell functions named
|
|
|
|
'alias' or 'unalias', overriding the commands by the same names. In
|
|
|
|
technical terms, they are now regular builtins, not special builtins.
|
|
|
|
|
2020-06-12 02:17:14 +00:00
|
|
|
- The redirect='command exec' alias has been converted to a regular
|
|
|
|
'redirect' builtin command that only accepts I/O redirections, which
|
|
|
|
persist as in 'exec'. This means that:
|
|
|
|
* 'unlias -a' no longer removes the 'redirect' command;
|
|
|
|
* users no longer accidentally get logged out of their shells if
|
|
|
|
they type something intuitive but wrong, like 'redirect ls >file'.
|
|
|
|
|
2020-06-12 04:57:57 +00:00
|
|
|
- The undocumented 'login' and 'newgrp' builtin commands have been removed.
|
|
|
|
These replaced your shell session with the external commands by the same
|
|
|
|
name, as in 'exec'. If an error occurred (e.g. due to a typo), you would
|
|
|
|
end up immediately logged out.
|
|
|
|
If you do want this behaviour, you can restore it by setting:
|
|
|
|
alias login='exec login'
|
|
|
|
alias newgrp='exec newgrp'
|
|
|
|
|
2020-06-10 11:00:35 +00:00
|
|
|
2020-06-10:
|
|
|
|
|
|
|
|
- The 'hash' utility is now a regular builtin instead of an alias to
|
|
|
|
'alias -t --'. The functionality of the old command has been removed
|
|
|
|
from the alias builtin.
|
|
|
|
|
|
|
|
- Changing the hash table in a subshell will no longer affect the parent
|
|
|
|
shell's hash table. This fix applies to the hash utility and when the
|
|
|
|
PATH is reset manually.
|
|
|
|
|
2020-06-09 15:31:00 +00:00
|
|
|
2020-06-09:
|
|
|
|
|
|
|
|
- The 'unalias' builtin will now return a non-zero status if it tries
|
|
|
|
to remove a previously set alias that is not currently set.
|
|
|
|
|
2020-06-07 22:01:24 +00:00
|
|
|
2020-06-08:
|
|
|
|
|
2020-06-10 12:16:53 +00:00
|
|
|
- Fix an issue with the up arrow key in Emacs editing mode.
|
|
|
|
Emacs editing mode is bugged in ksh93u+ and ksh2020. Let's
|
|
|
|
say you were to run the following commands after starting
|
|
|
|
a fresh instance of ksh:
|
|
|
|
$ alias foo='true'
|
|
|
|
$ unalias foo
|
|
|
|
If you type 'a' and then press the up arrow on your keyboard,
|
|
|
|
ksh will complete 'a' to `alias foo='true'` by doing a reverse
|
|
|
|
search for the last command that starts with 'a'.
|
|
|
|
Run the alias command again, then type 'u' and press the up
|
|
|
|
arrow key again. If ksh is in Vi mode, you will get `unalias foo`,
|
|
|
|
but in Emacs mode you will get `alias foo='true'` again.
|
|
|
|
All subsequent commands were ignored as ksh was saving the first
|
|
|
|
command and only based later searches off of it.
|
2020-06-08 10:22:51 +00:00
|
|
|
|
2020-06-07 22:01:24 +00:00
|
|
|
- If 'set -u'/'set -o nounset' is active, then the shell now errors out if a
|
|
|
|
nonexistent positional parameter such as $1, $2, ... is accessed, as other
|
|
|
|
shells do and POSIX requires. (This does *not* apply to "$@" and "$*".)
|
|
|
|
|
2020-06-07 23:05:27 +00:00
|
|
|
- If 'set -u'/'set -o nounset' is active, then the shell now errors out if $!
|
|
|
|
is accessed before the shell has launched any background process.
|
|
|
|
|
2020-06-08 01:28:36 +00:00
|
|
|
- Removed support for an obscure early 1990s Bell Labs file system research
|
|
|
|
project called 3DFS, which has not existed for decades. This removes:
|
|
|
|
- an obnoxious default alias 2d='set -f;_2d' that turned off your file name
|
|
|
|
wildcard expansion and then tried to run a nonexistent '_2d' command
|
|
|
|
- undocumented builtins 'vmap' and 'vpath' that only printed error messages
|
|
|
|
- a non-functional -V unary operator for the test and [[ commands
|
|
|
|
|
Fix signal handling due to exit status > 256
This fixes two bugs: issuing the 'exit' command with a value > 256
would cause ksh 93u+ to kill itself with the corresponding signal
(try 'exit 265' to SIGKILL your interactive shell), and, if the
last command of a script exits due to a signal, the shell would
repeat that signal to itself, causing any parent ksh to also be
killed.
Discussion:
https://bugzilla.redhat.com/show_bug.cgi?id=1469624
https://rainbow.chard.org/2017/03/21/ksh-deliberately-segfaults-if-the-last-command-in-a-script-crashes/
This commit is loosely based on a patch applied to the 93v- beta
and the abandoned ksh2020, but that patch was incomplete & broken:
$ ksh-2020.0.0 -c 'exit 265'; echo $?
137
Expected: 9. Since the exit was *not* due to a signal, the value
should simply be cropped to the 8 bits supported by the OS.
src/cmd/ksh93/bltins/cflow.c: b_exit():
- For the 'exit' builtin command, bitwise-AND the argument to
'exit' with SH_EXITMASK (8 bits, crop to 0-255) before passing it
on to sh_exit(). This restores the behaviour of <=2011 ksh93
versions and is in line with all other POSIX shells.
It also fixes this bogosity:
$ (exit 265); echo $? # non-forked subshell
265
$ (ulimit -t unlimited; exit 265); echo $? # forked subshell
9
Forked or non-forked should make no difference at all
(see commit message a0e0e29e for why).
src/cmd/ksh93/sh/fault.c: sh_done():
- If the current exit status is equal to the status for the last
signal that was received from a child process, remove the
SH_EXITSIG (9th) bit, so that the shell doesn't kill itself.
- If the shell's last child process exits due to a signal, exit
with a portable 8-bit exit status (128 + signal number). This
avoids the exit status being < 128 by being cropped to 8 bits.
src/cmd/ksh93/tests/signal.sh:
- Add regression test for exit with status > 256.
- Add regression test verifying the shell no longer kills itself.
(cherry picked from commit 98e0fc94393e175ce6adfee390327c320795bf12)
2020-06-08 10:23:37 +00:00
|
|
|
- If the last program run by a ksh script exits with a signal (e.g. crashed),
|
|
|
|
ksh itself now exits normally instead of repeating that same signal.
|
|
|
|
In addition, using 'exit x' for x > 256 no longer makes ksh issue a signal.
|
|
|
|
|
2020-06-06 19:25:59 +00:00
|
|
|
2020-06-06:
|
|
|
|
|
|
|
|
- The 'times' command is now a builtin command that conforms to POSIX
|
|
|
|
instead of an alias for the 'time' command. It displays the accumulated
|
|
|
|
user and system CPU times, one line with the times used by the shell and
|
|
|
|
another with those used by all of the shell's child processes.
|
|
|
|
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_27
|
|
|
|
|
POSIX compliance: rm harmful default aliases 'command '/'nohup '
Continuing alias substitution after 'command' (due to the final
space in the alias) is inherently broken and doing so by default is
incompatible with the POSIX standard, as aliases may contain
arbitrary shell grammar.
For instance, until the previous commit, the POSIX standard 'times'
command was an alias: times='{ { time;} 2>&1;}' -- and so, of
course, 'command times' gave a syntax error, although this is
a perfectly valid POSIX idiom that must be supported.
'command' is specified by POSIX as a regular builtin, not an alias.
Therefore it should always bypass aliases just as it bypasses
functions to expose standard builtin and external commands.
I can only imagine that the reason for this command='command '
alias was that some standard commands themselves were implemented
as aliases, and POSIX requires that standard commands are
accessible with the 'command' prefix. But implementing standard
commands as aliases is itself inherently broken. It never worked
for 'command times', as shown; and in any case, removing all
aliases with 'unalias -a' should not get rid of standard commands.
Similarly, the default alias nohup='nohup ' is also harmful.
Anyone who really wants to keep this behaviour can just define
these aliases themselves in their script or ~/.kshrc file.
src/cmd/ksh93/data/aliases.c:
- Remove default alias command='command '.
- Remove default alias nohup='nohup '.
src/cmd/ksh93/sh.1
- Remove the above default aliases from the list.
- Mention that the 'command' builtin does not search for aliases.
(cherry picked from commit 5cfe7c4e2015b7445da24983af5008035c4b6e1e)
2020-06-07 00:36:54 +00:00
|
|
|
- The default aliases command='command ' and nohup='nohup ' have been
|
|
|
|
removed because they caused breakage in an attempt to circumvent other
|
|
|
|
breakage which is being fixed. In the unlikely even that anyone still
|
|
|
|
needs alias substitution to continue on the command argument following
|
|
|
|
'command' or 'nohup', it's easy to set these aliases yourself.
|
|
|
|
|
Fix unsetting special vars in subshells (re: efa31503, 8b7f8f9b)
This fixes (or at least works around) a bug that caused special
variables such as PATH, LANG, LC_ALL, LINENO, etc. to lose their
effect after being unset in a subshell.
For example:
(unset PATH; PATH=/dev/null; ls); : wrongly ran 'ls'
(unset LC_ALL; LC_ALL=badlocale); : failed to print a diagnostic
This is yet another problem with non-forking/virtual subshells. If
you forced the subshell to fork (one way of doing this is using the
'ulimit' builtin, e.g. ulimit -t unlimited) before unsetting the
special variable, the problem vanished.
I've tried to localise the problem. I suspect the sh_assignok()
function, which is called from unall(), is to blame. This function
is supposed to make a copy of a variable node in the virtual
subshell's variable tree. Apparently, it fails to copy the
associated permanent discipline function settings (stored in the
np->nvfun->disc pointer) that gave these variables their special
effect, and which survive unset. However, my attempts to fix that
have been unsuccessful. If anyone can figure out a fix, please send
a patch/pull request!
Data point: This bug existed in 93u 2011-02-08, but did not yet
exist in M-1993-12-28-s+. So it is a regression.
Meanwhile, pending a proper fix, this commit adds a safe
workaround: it forces a non-forked subshell to fork before
unsetting such a special variable.
src/cmd/ksh93/bltins/typeset.c: unall():
- If we're in a non-forked, non-${ ...; } subshell, then before
unsetting any variable, check for variables with internal
trap/discipline functions, and call sh_subfork() if any are
found. To avoid crashing, this must be done before calling
sh_pushcontext(), so we need to loop through the args separately.
src/cmd/ksh93/tests/variables.sh:
- Remove the 'ulimit' that forced the fork; we do this in C now.
(cherry picked from commit 21b1a67156582e3cbd36936f4af908bb45211a4b)
2020-06-05 13:31:26 +00:00
|
|
|
2020-06-05:
|
|
|
|
|
|
|
|
- Fix a bug that caused special variables such as PATH, LANG, LC_ALL,
|
|
|
|
etc. to lose their effect after being unset in a subshell. For example:
|
|
|
|
(unset PATH; PATH=/dev/null; ls); : wrongly ran 'ls'
|
|
|
|
(unset LC_ALL; LC_ALL=badlocale); : failed to print a diagnostic
|
|
|
|
|
2020-06-05 14:03:07 +00:00
|
|
|
- Fix crashes on some systems, including at least a crash in 'print -v' on
|
|
|
|
macOS, by eliminating an invalid/undefined use of memccpy() on overlapping
|
|
|
|
buffers in the commonly used sfputr() function.
|
|
|
|
|
Fix ${.sh.subshell} counter to actually count level of subshells
This counter is documented as follows:
"The current depth for subshells and command substitution."
But before this commit, the actual behaviour was that the counter
was reset to zero whenever a subshell forked for any reason: a
pipe, background job, running 'ulimit', redirecting stdout in a
command substitution, and more. This behaviour was:
1. Not consistent with the documentation. Non-forked (a.k.a.
virtual) subshells are an internal implementation detail which
scripts should not have to be concerned with. The manual page
doesn't mention them at all.
2. Inherently broken. Since a subshell may fork for any number of
reasons, even mid-run, and those reasons may change with
bugfixes and further development, scripts have never actually
been able to rely on the value of ${.sh.subshell}.
So, this commit fixes the counter to count the levels of all
subshells, both virtual and forked.
src/cmd/ksh93/sh/xec.c: _sh_fork():
- Increase ${.sh.subshell} whenever we fork.
src/cmd/ksh93/sh/subshell.c:
- sh_subfork():
* Fix comment to properly explain what it does. It doesn't
"create" a subshell, it forks off an existing virtual subshell.
* Don't zero ${.sh.subshell}. Instead, since sh_fork() increases
it but we're forking an existing subshell, undo the increase.
- sh_subshell():
* Remove 'int16_t subshell' variable. It was unnecessary and
mostly unused. It was also the wrong type: it was assigned the
value from shp->subshell which is of type short.
* Increase and decrease the level of virtual subshells and
${.sh.subshell} independently.
src/cmd/ksh93/tests/variables.sh:
- Add regression tests for ${.sh.subshell} in virtual and forked
subshells of several kinds: comsub, parentheses, pipe, bg job.
- Undo wrong error test count fix from 04b4aef0.
(cherry picked from commit a0e0e29e7e0dbf21e4b3958ae02bde6665fb2696)
2020-06-05 19:39:47 +00:00
|
|
|
- Fix the ${.sh.subshell} level counter; it is no longer reset to zero when a
|
|
|
|
non-forked subshell happens to fork into a separate process for some reason
|
|
|
|
(an internal implementation detail that should be unnoticeable to scripts).
|
|
|
|
|
Fix BUG_KBGPID: $! was not updated under certain conditions
The $! special parameter was not set if a background job
(somecommand &) or co-process (somecommand |&) was launched as the
only command within a braces block with an attached redirection,
for example:
{
somecommand &
} >&2
With the bug, $! was unchanged; now it contains the PID of
somecommand.
Ref.: https://github.com/att/ast/issues/1357
src/cmd/ksh93/sh/parse.c: item():
- When processing redirections following a compound command, always
create a parent node with the TSETIO (I/O redirection) token.
Before this commit, if the last command was of type TFORK (and
the last command only tested as TFORK if the bg job or coprocess
was the only command in a braces block, because the ksh parser
optimises away the braces in that case), then the parent node was
created with the TFORK token instead.
I have no idea what David Korn's intention was with that, but
this is clearly very wrong. Creating another TFORK node when
parsing the redirection caused sh_exec() in sh/xec.c to execute
the redirection in an extra forked, non-background subshell.
Since redirections are executed before anything else, this
subshell is what then launched the background job between the
braces, so $! (a.k.a. shp->bckpid) was updated in that subshell
only, and never in the main shell. The extra subshell also
prevented the background job from being noticed by job control
on interactive shells.
So, the fix is simply to remove the broken test for TFORK.
src/cmd/ksh93/tests/variables.sh:
- Add regression tests for a bg job and a co-process as the only
command within a braces block with attached redirection.
(cherry picked from commit ffe5df30e69f7b596941a98498014d8e838861f2)
2020-06-04 03:19:59 +00:00
|
|
|
2020-06-04:
|
|
|
|
|
|
|
|
- Fix BUG_KBGPID: the $! special parameter was not set if a background job
|
|
|
|
(somecommand &) or co-process (somecommand |&) was launched as the only
|
|
|
|
command within a braces block with an attached redirection, for example:
|
|
|
|
{
|
|
|
|
somecommand &
|
|
|
|
} >&2
|
|
|
|
With the bug, $! was unchanged; now it contains the PID of somecommand.
|
|
|
|
|
2020-05-31 13:29:15 +00:00
|
|
|
2020-05-31:
|
|
|
|
|
|
|
|
- Fix a bug in autoloading functions. Directories in the path search list
|
|
|
|
which should be skipped (e.g. because they don't exist) did not interact
|
|
|
|
correctly with autoloaded functions, so that a function to autoload was
|
|
|
|
not always found correctly.
|
|
|
|
Details: https://github.com/att/ast/issues/1454
|
|
|
|
|
2020-05-30 14:21:30 +00:00
|
|
|
2020-05-30:
|
|
|
|
|
|
|
|
- Fix POSIX compliance of 'test'/'[' exit status on error. The command now
|
|
|
|
returns status 2 instead of 1 when given an invalid number or arithmetic
|
|
|
|
expression, e.g.:
|
|
|
|
[ 123 -eq 123x ]; echo $?
|
|
|
|
now outputs 2 instead of 1.
|
|
|
|
|
Fix redefining & unsetting functions in subshells (BUG_FNSUBSH)
Functions can now be correctly redefined and unset in subshell
environments (such as ( ... ), $(command substitutions), etc).
Before this fix, attempts to do this were silently ignored (!!!),
causing the wrong code (i.e.: the function by the same name from
the parent shell environment) to be executed.
Redefining and unsetting functions within "shared" command
substitutions of the form '${ ...; }' is also fixed.
Prior discussion: https://github.com/att/ast/issues/73
src/cmd/ksh93/sh/parse.c:
- A fix from George Koelher (URL above). He writes:
| The parser can set t->comnamp to the wrong function.
| Suppose that the shell has executed
| foo() { echo WRONG; }
| and is now parsing
| (foo() { echo ok; } && foo)
| The parser was setting t->comnamp to the wrong foo. [This
| fix] doesn't set t->comnamp unless it was a builtin. Now the
| subshell can't call t->comnamp, so it looks for foo and finds
| the ok foo in the subshell's function tree.
src/cmd/ksh93/bltins/typeset.c:
- Unsetting functions in a virtual/non-forked subshell still
doesn't work: nv_open() fails to find the function. To work
around this problem, make 'unset -f' fork the subshell into its
own process with sh_subfork().
- The workaround exposed another bug: if we unset a function in a
subshell tree that overrode a function by the same name in the
main shell, then nv_delete() exposes the function from the main
shell scope. Since 'unset -f' now always forks a subshell, the
fix is to simply walk though troot's parent views and delete any
such zombie functions as well. (Without this, the 4 'more fun'
tests in tests/subshell.sh fail.)
src/cmd/ksh93/sh/subshell.c: sh_subfuntree():
- Fix function (re)definitions and unsetting in "shared" command
substitutions of the form '${ commandlist; }' (i.e.: if
sp->shp->subshare is true). Though internally this is a weird
form of virtual subshell, the manual page says it does not
execute in a subshell (meaning, all changes must survive it), so
a subshell function tree must not be created for these.
src/cmd/ksh93/tests/subshell.sh:
- Add regression tests related to these bugfixes. Test unsetting
and redefining a function in all three forms of virtual subshell.
(cherry picked from commit dde387825ab1bbd9f2eafc5dc38d5fd0bf9c3652)
2020-05-29 07:27:20 +00:00
|
|
|
2020-05-29:
|
|
|
|
|
|
|
|
- Fix BUG_FNSUBSH: functions can now be correctly redefined and unset in
|
|
|
|
subshell environments (such as ( ... ), $(command substitutions), etc).
|
|
|
|
Before this fix, this was silently ignored, causing the function by the
|
|
|
|
same name from the parent shell environment to be executed instead.
|
|
|
|
fn() { echo mainsh; }
|
|
|
|
(fn() { echo subsh; }; fn); fn
|
|
|
|
This now correctly outputs "subsh mainsh" instead of "mainsh mainsh".
|
|
|
|
ls() { echo "ls executed"; }
|
|
|
|
(unset -f ls; ls); ls
|
|
|
|
This now correctly lists your directory and then prints "ls executed",
|
|
|
|
instead of printing "ls executed" twice.
|
|
|
|
|
Fix unsetting aliases in subshells
Aliases can now be correctly unset within subshell environments
(such as ( ... ), $(command substitutions), etc), as well as
non-subshell "shared" command substitutions (${ ...; }). Before,
attempts to unset aliases within these were silently ignored.
Prior discussion: https://github.com/att/ast/issues/108
Subshell alias trees are only referenced in a few places in the
code, *and* have always been broken, so this commit gets rid of the
whole notion of a subshell alias tree. Instead, there is now just
one flat alias tree, and subshells fork into a separate process
when aliases are set or unset within them. It is not really
conceivable that this could be a performance-sensitive operation,
or even a common one, so this is a clean fix with no downside.
src/cmd/ksh93/include/defs.h:
- Remove sh_subaliastree() definition.
src/cmd/ksh93/sh/subshell.c:
- Remove salias element (pointer to subshell alias tree) from
subshell struct.
- Remove sh_subaliastree() function.
- sh_subshell(): Remove alias subshell tree cleanup.
src/cmd/ksh93/bltins/typeset.c:
- b_alias(): If in subshell, fork before setting alias.
- b_unalias(): If in subshell, fork before unsetting alias.
- unall(): Remove sh_subaliastree() call.
src/cmd/ksh93/sh/name.c:
- nv_open(): Remove sh_subaliastree() call.
src/cmd/ksh93/tests/subshell.sh:
- Add regression tests for unsetting or redefining aliases within
subshells.
(cherry picked from commit 12a15605b9521a2564a6e657905705a060e89095)
2020-05-29 07:27:53 +00:00
|
|
|
- Fix a similar bug with aliases. These can now be correctly unset
|
|
|
|
in subshell environments.
|
|
|
|
|
2020-05-20 21:42:00 +00:00
|
|
|
2020-05-21:
|
|
|
|
|
|
|
|
- Fix truncating of files with the combined redirections '<>;file' and
|
|
|
|
'<#pattern'. The bug was caused by out-of-sync streams.
|
|
|
|
Details and discussion: https://github.com/att/ast/issues/61
|
|
|
|
|
2020-05-30 14:55:30 +00:00
|
|
|
- Patched code injection vulnerability CVE-2019-14868. As a result, you can
|
2020-05-21 12:27:51 +00:00
|
|
|
no longer use expressions in imported numeric environment variables; only
|
|
|
|
integer literals are allowed.
|
|
|
|
|
Fix bugs in testing if a parameter is set
This fixes three related bugs:
1. Expansions like ${var+set} remained static when used within a
'for', 'while' or 'until' loop; the expansions din't change
along with the state of the variable, so they could not be used
to check whether a variable is set within a loop if the state of
that variable changed in the course of the loop. (BUG_ISSETLOOP)
2. ${IFS+s} always yielded 's', and [[ -v IFS ]] always yielded
true, even if IFS is unset. (BUG_IFSISSET)
3. IFS was incorrectly exempt from '-u' ('-o nounset') checks.
src/cmd/ksh93/sh/macro.c: varsub():
- When getting a node pointer (np) to the parameter to test,
special-case IFS by checking if it has a value and not setting
the pointer if not. The node to IFS always exists, even after
'unset -v IFS', so before this fix it always followed the code
path for a parameter that is set. This fixes BUG_IFSISSET for
${IFS+s} and also fixes set -u (-o nounset) with IFS.
- Before using the 'nv_isnull' macro to check if a regular variable
is set, call nv_optimize() if needed. This fixes BUG_ISSETLOOP.
Idea from Kurtis Rader: https://github.com/att/ast/issues/1090
Of course this only works if SHOPT_OPTIMIZE==1 (the default),
but if not, then this bug is not triggered in the first place.
- Add some comments for future reference.
src/cmd/ksh93/bltins/test.c: test_unop():
- Fix BUG_IFSISSET for [[ -v IFS ]]. The nv_optimize() method
doesn't seem to have any effect here, so the only way that I can
figure out is to special-case IFS, nv_getval()'ing it to check if
IFS has a value in the current scope.
src/cmd/ksh93/tests/variables.sh:
- Add regression tests for checking if a varariable is set within a
loop, within and outside a function with that variable made local
(to check if the scope is honoured). Repeat these tests for a
regular variable and for IFS, for ${foo+set} and [[ -v foo ]].
(cherry picked from commit a2cf79cb98fa3e47eca85d9049d1d831636c9b16)
2020-05-20 14:50:43 +00:00
|
|
|
2020-05-20:
|
|
|
|
|
|
|
|
- Fix BUG_ISSETLOOP. Expansions like ${var+set} remained static when used
|
|
|
|
within a 'for', 'while' or 'until' loop; the expansions din't change along
|
|
|
|
with the state of the variable, so they could not be used to check whether a
|
|
|
|
variable is set within a loop if the state of that variable changed in the
|
|
|
|
course of the loop.
|
|
|
|
|
|
|
|
- Fix BUG_IFSISSET. ${IFS+s} always yielded 's', and [[ -v IFS ]] always
|
|
|
|
yielded true, even if IFS is unset. This applied to IFS only.
|
|
|
|
|
2020-05-19 14:49:56 +00:00
|
|
|
2020-05-19:
|
|
|
|
|
|
|
|
- Fix 'command -p'. The -p option causes the operating system's standard
|
|
|
|
utilities path (as output by 'getconf PATH') to be searched instead of $PATH.
|
|
|
|
Before this fix, this was broken on non-interactive shells as the internal
|
|
|
|
variable holding the default PATH value was not correctly initialised.
|
|
|
|
|
Fix 'test -t 1' in $(command substitutions)
Standard output (FD 1) tested as being on a terminal within a
command substitution, which makes no sense as the command
substitution is supposed to be catching standard output.
ksh -c 'v=$(echo begincomsub
[ -t 1 ] && echo oops
echo endcomsub)
echo "$v"'
This should not output "oops".
This is one of the many bugs with ksh93 virtual (non-forked)
subshells. On the abandoned Vashist/Rader ksh2020 branch, this bug
was fixed by changing quite a lot of code, which introduced and/or
exposed another bug:
https://github.com/att/ast/issues/1079
https://github.com/att/ast/commit/8e1e405e
https://github.com/att/ast/issues/1088
That issue was unresolved when the ksh2020 branch was abandoned.
The safer and more conservative fix is simply forcing the subshell
to fork if we're in a non-forked command substitution and testing
'-t 1'. It is hard to imagine a situation where this would cause a
noticable performance hit.
Note that this fix does not affect ksh93-specific "shared"
non-subshell ${ command substitutions; } which are executed in the
main shell environment, so that variables survive, etcetera.
'test -t 1' continues to wrongly return true there, but command
substitutions of that form cannot be forked because that would
defeat their purpose.
src/cmd/ksh93/bltins/test.c:
- Fix 'test -t 1', '[ -t 1 ]' and '[[ -t 1 ]]' by forking the
current subshell if it is a virtual/non-forked subshell
(shp->subshell), and a command substitution (shp->comsub), but
NOT a "shared" ${ command substitution; } (!shp->subshare).
src/cmd/ksh93/tests/bracket.sh:
- Add two regression tests for this issue, which were adapted from
the Vashist/Rader ksh2020 branch.
NEWS, src/cmd/ksh93/include/version.h:
- Update.
(cherry picked from commit b8ef05e457ead65b83417699b8dd8632f855e2fa)
2020-05-16 19:06:49 +00:00
|
|
|
2020-05-16:
|
|
|
|
|
|
|
|
- Fix 'test -t 1', '[ -t 1 ]', '[[ -t 1 ]]' in command substitutions.
|
|
|
|
Standard output (file descriptor 1) tested as being on a terminal within a
|
|
|
|
command substitution, which makes no sense as the command substitution is
|
|
|
|
supposed to be catching standard output.
|
|
|
|
v=$(echo begincomsub
|
|
|
|
[ -t 1 ] && echo oops
|
|
|
|
echo endcomsub)
|
|
|
|
echo "$v"
|
|
|
|
This now does not output "oops".
|
|
|
|
|
2020-05-14 10:36:16 +00:00
|
|
|
2020-05-14:
|
|
|
|
|
|
|
|
- Fix syncing history when print -s -f is used. For example, the
|
|
|
|
following now correctly adds a 'cd' command to the history:
|
|
|
|
print -s -f 'cd -- %q\n' "$PWD"
|
|
|
|
Ref.: https://github.com/att/ast/issues/425
|
|
|
|
https://github.com/att/ast/pull/442
|
|
|
|
|
2020-06-09 19:57:05 +00:00
|
|
|
- Fix BUG_PUTIOERR: Output builtins now correctly detect
|
2020-05-16 14:04:35 +00:00
|
|
|
input/output errors. This allows scripts to check for a nonzero exit
|
|
|
|
status on the 'print', 'printf' and 'echo' builtins and prevent possible
|
|
|
|
infinite loops if SIGPIPE is ignored.
|
|
|
|
|
2020-05-14 16:41:26 +00:00
|
|
|
- Add a convenient bin/run_ksh_tests script to the source tree that
|
|
|
|
sets up the necessary environment and runs the ksh regression tests.
|
|
|
|
|
Fix BUG_CASELIT: pattern matching as literal string in 'case'
This fixes an undocumented 'case' pattern matching misbehaviour
(labelled BUG_CASELIT in modernish) that goes back to the original
Bourne shell, but wasn't discovered until 2018.
If a pattern doesn't match as a pattern, it's tried again as a
literal string. This breaks common validation use cases, such as:
n='[0-9]'
case $n in
( [0-9] ) echo "$n is a number" ;;
esac
would output "[0-9] is a number" as the literal string fallback
matches the pattern. As this misbehaviour was never documented
anywhere (not for Bourne, ksh88, or ksh93), and it was never
replicated in other shells (not even in ksh88 clones pdksh and
mksh), it is unlikely any scripts rely on it.
Of course, a literal string fallback, should it be needed, is
trivial to implement correctly without this breakage:
case $n in
( [0-9] | "[0-9]") echo "$n is a number or the number pattern" ;;
esac
src/cmd/ksh93/sh/xec.c:
- Remove trim_eq() function responsible for implementing the
misbehaviour described above.
NEWS:
- Added. Document this bugfix.
Ref.:
- The problem: thread starting at
https://www.mail-archive.com/austin-group-l@opengroup.org/msg02127.html
- The solution, thanks to George Koehler: comments/commits in
https://github.com/att/ast/issues/476
- Modernish BUG_CASELIT bug test & documentation:
https://github.com/modernish/modernish/commit/b2024ae3
(cherry picked from commit 8d6c8ce69884767a160c1e20049e77bdd849c248
with some extra edits to NEWS to upate the info for this reboot)
2020-06-11 15:14:31 +00:00
|
|
|
2020-05-13:
|
|
|
|
|
|
|
|
- Fix BUG_CASELIT: an undocumented 'case' pattern matching misbehaviour that
|
|
|
|
goes back to the original Bourne shell, but wasn't discovered until 2018.
|
|
|
|
If a pattern doesn't match as a pattern, it was tried again as a literal
|
|
|
|
string. This broke common validation use cases, e.g.:
|
|
|
|
n='[0-9]'
|
|
|
|
case $n in
|
|
|
|
( [0-9] ) echo "$n is a number" ;;
|
|
|
|
esac
|
|
|
|
would output "[0-9] is a number" as the literal string fallback matches the
|
|
|
|
pattern. As this misbehaviour was never documented anywhere (not for Bourne,
|
|
|
|
ksh88, or ksh93), and it was never replicated in other shells (not even in
|
|
|
|
ksh88 clones pdksh and mksh), it is unlikely any scripts rely on it.
|
|
|
|
Of course, a literal string fallback, should it be needed, is trivial to
|
|
|
|
implement correctly without this breakage:
|
|
|
|
case $n in
|
|
|
|
( [0-9] | "[0-9]") echo "$n is a number or the number pattern" ;;
|
|
|
|
esac
|
2020-05-13 14:00:33 +00:00
|
|
|
Ref.: https://github.com/att/ast/issues/476
|
|
|
|
|
|
|
|
- Fix BUG_REDIRIO: ksh used to redirect standard output by default when no
|
|
|
|
file descriptor was specified with the rarely used '<>' reading/writing
|
|
|
|
redirection operator. It now redirects standard input by default, as POSIX
|
|
|
|
specifies and as all other POSIX shells do. To redirect standard output
|
|
|
|
for reading and writing, you now need '1<>'.
|
|
|
|
Ref.: https://github.com/att/ast/issues/75
|
|
|
|
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_07
|