1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00
Commit graph

84 commits

Author SHA1 Message Date
Martijn Dekker
d024d4c895 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-12 01:45:17 +02:00
Martijn Dekker
f88f302c38 Remove code related to long-dead 3DFS research project
This commit gets rid of dead weight related to an obscure early
1990s Bell Labs versioning file system research project called
3DFS, which has not existed for decades and for which I have not
managed to find any evidence that it was ever used outside the lab.

This removes:
- the SHOPT_FS_3D compile option (which was forced on even when 0)
- the obnoxious default alias 2d='set -f;_2d' that turned off your
  globbing and then tried to run a nonexistent _2d command
- undocumented builtins 'vmap' and 'vpath' that only errored out
- a non-functional -V unary operator for the test and [[ commands
- some specific code for Apollo workstations (last made in 1997),
  which was inseparably intertwined with the 3DFS code

(cherry picked from commit 20cdf3709f4fb4e468057b534dcee819b1961fb6)
2020-06-12 01:45:17 +02:00
Martijn Dekker
5f8b0512f0 POSIX compliance fix: apply 'set -u' to $!
POSIX requires[*] that expanding any unset parameter other than $@
and $* is an error when 'set -u'/'set -o nounset' is active.
However, on ksh93, $! was exempt as well. That is a bug.
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_25

src/cmd/ksh93/sh/macro.c:
- special(): Handle 'set -u' for special parameters if/when it is
  about to return NIL. That code path is currently only possible to
  reach for "$!", but this is future-proof and will do the right
  thing if any other special parameter can ever have no value.

src/cmd/ksh93/tests/options.sh:
- Add and tweak 'set -u' regression tests.

(cherry picked from commit 75cc7a38cafe3a9929e1ed17d8b952babda22a09)
2020-06-12 01:45:17 +02:00
Martijn Dekker
36da314c9e POSIX compliance fix: apply 'set -u' to $1, $2, ...
POSIX requires[*] that expanding any unset parameter other than $@
and $* is an error when 'set -u'/'set -o nounset' is active.
However, on ksh93, $1, $2, ... were exempt as well. That is a bug.
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_25

src/cmd/ksh93/sh/macro.c:
- varsub(): Backport code for handling 'set -u' for positional
  parameters from the ast 2016-10-01-beta branch.

src/cmd/ksh93/tests/options.sh:
- Add relevant regression tests.

src/cmd/ksh93/sh.1:
- Document that $@ and $* are exempt from 'set -u'.

(cherry picked from commit f954c6be0748c4c38a680a75f27564965fbd328e)
2020-06-12 01:45:17 +02:00
Martijn Dekker
e2a648b41f tests/options.sh: fix child shell test by exporting variable
src/cmd/ksh93/tests/options.sh:
- Pipe hang bugfix test: The child shell has no idea how long to
  sleep for if we don't export the variable telling it so.

(cherry picked from commit ede0960c4ec84f0f934b17072a892a4e40798e97)
2020-06-12 01:45:17 +02:00
Martijn Dekker
781f0a39aa Fix parsing of multibyte characters
According to Red Hat, this fixes "a bug on input buffer boundary
and/or temporary composing buffer of multibyte characters".
The patch was credited to Paulo Andrade <pandrade@redhat.com>.

To be honest, I don't know how to trigger this bug or what the code
removed by this fix really does, but this patch is in production
use at Red Hat, removes some smelly stuff, and is not triggering
any regression test failures, so I'll just take this one on faith.

https://bugzilla.redhat.com/show_bug.cgi?id=1417886
https://github.com/att/ast/commit/4fa2020b

src/cmd/ksh93/sh/fcin.c:
- _fcmbget(): Remove some dodgy-looking buffer-fiddling code that
  is marked as "for testing purposes with small buffers".

(cherry picked from commit 407760fdbddcb7f8ac92b5d1da29d3e09dac0369)
2020-06-12 01:45:17 +02:00
Martijn Dekker
7559f83eff Fix ksh hanging in pipes
Under certain conditions, ksh scripts may hang when piped through
a program that terminates before EOF.

Discussion and reproducer:
https://bugzilla.redhat.com/show_bug.cgi?id=1457990
https://www.mail-archive.com/ast-developers@lists.research.att.com/msg01961.html

src/cmd/ksh93/sh/jobs.c:
- In job_wait(), correctly set the terminal foreground process
  group when resuming a process.

(cherry picked from commit 99ef2ca5309da91fdead74bea00743960d470c6a)
2020-06-12 01:45:16 +02:00
Martijn Dekker
98c1e37d86 Fix memory corruption while parsing functions
Discussion: https://bugzilla.redhat.com/show_bug.cgi?id=1451057

src/cmd/ksh93/sh/parse.c: funct():
- Make the savstak variable volatile and always initialise it to
  avoid undefined behaviour.

(cherry picked from commit 5e56b28cd63ec2120c5f70a6e0abf2f8dbb7e7dc)
2020-06-12 01:45:16 +02:00
Martijn Dekker
b9f28bc508 cleanup: remove pointless no-op 'fc' and 'type' aliases
Both 'fc' and 'type' are already implemented as perfectly
functional builtins -- in fact they use the exact same C function
as 'hist' and 'whence', so the behaviour is clearly identical.

Except 'type' was aliased to 'whence -v', but b_whence() contains
explicit code to activate the v flag if invoked as 'type', so the
alias is not needed for that either.

It looks like someone decided to implement these aliases as proper
builtins (as they should be; they are POSIX standard commands and
'unalias -a' must not get rid of them), but then forgot to remove
these default aliases (and to update the man page).

I'm not even doing a NEWS entry for this as there is no change in
behaviour. The only difference is that you now get the correct
command name in error and usage messages for 'fc' and 'type'.

src/cmd/ksh93/data/aliases.c:
- Remove fc='hist' and type='whence -v' default aliases.

src/cmd/ksh93/sh.1:
- Remove those default aliases from the list.
- Document 'fc' and 'type' builtins.

(cherry picked from commit c73af6a5a36a72c681201c9e9c397f98bbf2a86d)
2020-06-12 01:45:16 +02:00
Martijn Dekker
61d9bca581 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-12 01:45:16 +02:00
Martijn Dekker
65d363fd34 POSIX compliance fix: make 'times' a proper builtin
As of this commit, the 'times' command is a POSIX-compliant special
builtin command instead of an alias that doesn't produce the
required output. 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

This was originally written by Kurtis Rader and is now backported
and tweaked from the abandoned ksh2020 branch. I chose an earlier
and simpler version[*1] that uses times(3), with a precision of
hundredths of seconds, so it outputs the same precision as mksh and
zsh. Rader later wrote another version[*2] that uses getrusage(2),
giving it the same millisecond precision as bash. But that required
adding a feature test and a fallback to the old version, which is
non-trivial in the old INIT/iffe system. This simpler version is
enough to gain POSIX compliance and I think it will do very nicely
in this stable bugfix branch.

[*1] https://github.com/att/ast/pull/1332
[*2] https://github.com/att/ast/commit/038045f6

src/cmd/ksh93/bltins/misc.c
- Add b_times() function for 'times' builtin.
- Note we include <times.h>, not <sys/times.h>, so that we use the
  AST feature-tested version with fallback on systems that need it.

src/cmd/ksh93/data/aliases.c:
- Remove times='{ { time;} 2>&1;}' builtin alias.

src/cmd/ksh93/data/builtins.c,
src/cmd/ksh93/include/builtins.h:
- Add entry for 'times' special builtin.
- Add --help/--man info for same.

src/cmd/ksh93/sh.1:
- Update manual page.

src/cmd/ksh93/tests/builtins.sh:
- Add a couple of simple regression tests.

(cherry picked from commit ebf71e619eb298ec1cf6b81d1828fa7cdf6e9203)
2020-06-12 01:45:16 +02:00
Martijn Dekker
3a3776f1df INIT/cc.darwin: re-suppress redefined macro warnings (re: a1d8ff6f)
Allowing redefined macro warnings was not such a good idea, as the
Apple compiler flags redefine the _ast_int8_t macro right on the
command line, producing a warning for every cc invocation.

(cherry picked from commit 929930224f898cb1371471fe554fabb73b31d11f)
2020-06-12 01:45:16 +02:00
Martijn Dekker
778b3da79a manual page: correct conditions under which shell is interactive
Only standard error needs to be on a terminal for a
shell to be interactive on init, not all output.

See sh_main() in src/cmd/ksh93/sh/main.c, under
"/* decide whether shell is interactive */".

Also, tcgetattr is not a syscall, so its manual page is
tcgetattr(3), not tcgetattr(2).

(cherry picked from commit 97f8bdb08650fd63f8e125257a86f5e6035fbdfa)
2020-06-12 01:45:16 +02:00
Martijn Dekker
d8a2b4fa6d manual page: fix documentation of default path
It didn't mention that the default path is obtained from the
operating system where available, and that the default string
documented is only a fallback (which, btw, should never occur on
modern systems).

See:
e_defpath[] in src/cmd/ksh93/data/msg.c
defpath_init() in src/cmd/ksh93/sh/path.c

src/cmd/ksh93/sh.1:
- Add a mention that the default path is equal to the output of
  ksh's 'getconf PATH' builtin command, unless that fails.

(cherry picked from commit 12b8dc54626a14171d3671a26041733a32e0e07d)
2020-06-12 01:45:16 +02:00
Martijn Dekker
7a421ba57f INIT: tweak cc.{darwin,freebsd}; add cc.openbsd
(cherry picked from commit a1d8ff6faca522a29161582952e232afc76fd643)
2020-06-12 01:45:16 +02:00
Martijn Dekker
8e97419b0b 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-12 01:45:16 +02:00
Martijn Dekker
6c68b53170 For consistency & greppability: global replace "sub-shell" => "subshell"
(cherry picked from commit 25eeb9bcdc0a23a66765fd3e5d7e36337da65051)
2020-06-12 01:45:16 +02:00
Martijn Dekker
8b07d2a011 Fix various crashes by removing invalid memccpy() use
The sfputr() function (put out a null-terminated string) contained
a use of memccpy() that was invalid and could cause crashes,
because the buffer it was copying into could overlap or even be
identical with the buffer being copied from.

Among (probably) other things, this commit fixes a crash in 'print
-v' (print a compound variable structure) on macOS, that caused the
comvar.sh and comvario.sh regression tests to fail spectacularly.
Now they pass.

Issue discovered and fixed by Kurtis Rader in the abandoned ksh2020
branch; this commit backports the fix. He wrote:

| #if _lib_memccpy && !__ia64 /* these guys may never get it right */
|
| The problem is that assertion is wrong. It implies that the libc
| implementation of memccpy() on IA64 is broken. Which is
| incorrect. The problem is the AST sfputr() function is depending
| on what is explicitly undefined behavior in the face of
| overlapping source and destination buffers.
| [...] Using memccpy() simply complicates the code and is unlikely
| to be measurably, let alone noticeably, faster.

Further discussion/analysis: https://github.com/att/ast/issues/78

src/lib/libast/sfio/sfputr.c:
- Remove memccpy use. Always use the manual copying loop.

(cherry picked from commit fbe3c83335256cb714a4aa21f555083c9f1d71d8)
2020-06-12 01:45:16 +02:00
Martijn Dekker
6f0e008cf7 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-12 01:45:16 +02:00
Martijn Dekker
04722950bb tests/variables.sh: fix subshell error count, & another xtrace caught in comsub
(cherry picked from commit 04b4aef0cf14d255ee27305f1458b34a1d3b8b6c)
2020-06-12 01:45:15 +02:00
Martijn Dekker
b6b8b522a7 regress tests: remove use of unportable direct paths to commands
Many tests used direct paths to some commands, mostly /bin/echo and
/bin/cat. This is unportable (breaks on e.g. NixOS).
The correct way is to obtain the direct path using 'whence -p'.

There was also one use of '/usr/bin/pstack' in tests/comvario.sh
that seemed bogus. Apparently this was supposed to analyse a core
file after a crash. Even on Solaris and Linux, where that command
exists, the argument is documented to be a PID, not a core file. If
this ever worked anywhere, then it was system-specific enough to be
useless here, so I've removed it.

(cherry picked from commit 4563b8bc651cd9cb18dc73f56a041f7ac5534395)
2020-06-12 01:45:15 +02:00
Martijn Dekker
3552a2bafd Restore building on old Mac OS X (Darwin) with GCC (re: e74e98b8)
In making ksh build on new macOS, it stopped building on old Mac OS
X (old gcc-based Darwin). There is no real reason for this. We can
just restore the old cc wrapper script and use it if an old gcc
compiler is detected.

This is only tested on Mac OS X 10.3 on my old Power Mac G5 so far.
But at least that allows me to test fixes on that platform. Unusual
platforms sometimes expose corner case bugs...

bin/package, src/cmd/INIT/package.sh:
- If /usr/bin/cc is GCC, change 'darwin' host name to 'darwin_old'.
  This removes the long-obsolete 'darwin7' host name.

src/cmd/INIT/cc.darwin_old:
- Restore the old cc.darwin script for darwin_old hosts.

(cherry picked from commit 93d4c6497ea8e9cc9f4977b75d06a673a2229f80)
2020-06-12 01:45:15 +02:00
Martijn Dekker
794d1c8601 shtests: report signal when a test crashes
When a test aborted due to a signal, the >256 exit code signifying
the signal was incorrectly reported as the number of errors.

src/cmd/ksh93/tests/shtests:
- For $? > 256, obtain and report the signal name using 'kill -l'.

(cherry picked from commit a7d8ae628e228fc3cadcf977fbffc87b90c7bc53)
2020-06-12 01:45:15 +02:00
Martijn Dekker
21f281a5fa tests/variables.sh: update virtual subshell failure TODO
Namerefs aren't broken in virtual/non-forked subshells after all
(phew). It is changing the locale that is somehow broken.

src/cmd/ksh93/tests/variables.sh:
- Pending further investigation, update the TODO and don't fork the
  subshell until actually needed.

(cherry picked from commit efa3150396b383b6a68b2df45eab9005593b2e42)
2020-06-12 01:45:15 +02:00
Martijn Dekker
759157bdb2 Fix hang in unsetting functions in subshells (re: dde38782)
This fixes a really stupid bug in my own code for unsetting a
function in a subshell. The algorithm for walking through the
subshell tree was broken, resulting in an infinite loop if there
were multiple levels of subshell.

src/cmd/ksh93/bltins/typeset.c:
- Correct the subshell function tree walk that deletes functions
  from zombie parent scopes.

src/cmd/ksh93/tests/subshell.sh:
- Add a regression test for setting and unsetting identically named
  functions in multiple levels of subshell.

(cherry picked from commit 972a7999c7f16469138daf3d86dfd6c0db3f4879)
2020-06-12 01:45:15 +02:00
Martijn Dekker
1026006db3 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-12 01:45:15 +02:00
Martijn Dekker
a9351320ed tests/variables.sh: fix problems with tracing ('bin/shtests -x')
src/cmd/ksh93/tests/variables.sh:
- Unset -x in a command substitution that redirects stderr to
  stdout; this caused a spurious failure with tracing active.
- Execute the nameref tests in a subshell. They modified LINENO, so
  that all the line numbers after this test were traced and/or
  reported as 'foo'.
  . This exposed a bug in namerefs: this is yet another thing that
    is broken in non-forked/virtual subshells! That is for another
    commit. For now, fork the subshell and leave a TODO.

(cherry picked from commit 8b7f8f9b14523a66bdf337612daef2501c2bb5ba)
2020-06-12 01:45:15 +02:00
Martijn Dekker
80126062cc tests/bracket.sh: don't test r/w perms as root; fix typos
src/cmd/ksh93/tests/bracket.sh:
- -r and -w are always true when running as root, so skip these.
- Fix several typos in the [[ tests (apparent copy/paste errors).

(cherry picked from commit b9325e9753b38f087d0c5501d474f7d1f15c4d36)
2020-06-12 01:45:15 +02:00
Martijn Dekker
e1ef18c8ef tests/builtin.sh: don't use unportable 'seq' (is not on OpenBSD)
(cherry picked from commit c9f6c148bff1fe82cb575d55467f68f2bef939ff)
2020-06-12 01:45:15 +02:00
Martijn Dekker
eee47df423 Fix handling of skipped directories when autoloading functions
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.

Details:
https://github.com/att/ast/issues/1454

Fix backported (and cleaned up) from:
https://github.com/att/ast/commit/3bc58164

src/cmd/ksh93/sh/path.c:
- path_opentype(): Fix the path search loop so that entries marked
  with PATH_SKIP are handled correctly.

src/cmd/ksh93/tests/functions.sh:
- Add regression test verifying an autoloaded function with a PATH
  that triggered the bug.
  The bug in path_opentype() fixed by this commit may affect other
  scenarios but we know it affects autoloaded functions. Hence the
  test for that scenario.

(cherry picked from commit a27903165775309f4f032de5d42ec1785f14cfbc)
2020-06-12 01:45:15 +02:00
Martijn Dekker
482d1c3dd6 fix 24 more typos found with the help of codespell
(cherry picked from commit a92198bc5f196ec1b4a34dc042ff3a594e316ad7)
2020-06-12 01:45:15 +02:00
Martijn Dekker
7003aba487 Fix 'test'/'[' exit status >1 on error in arithmetic expression
Fix BUG_TESTERR1A: POSIX non-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 ]

The problem was that the test builtin (b_test()) calls the generic
arithmetic evaluation subsystem (sh/arith.c, sh/streval.c) which
has no awareness of the test builtin. A simple solution would be to
always make the arithmetic subsystem use an exit status > 1 for
arithmetic errors, but globally changing this may cause backwards
compatibility issues. So it's best to change the behaviour of the
'test' builtin only. This requires the arithmetic subsystem to be
aware of whether it was called from the 'test' builtin or not. To
that end, this commit adds a global flag and overrides the
ERROR_exit macro where needed.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/defs.c:
- Declare and initialise a global sh_in_test_builtin flag.
- Declare internal function for ERROR_exit override in test.c.

src/cmd/ksh93/bltins/test.c:
- Add override for ERROR_exit macro using a function that checks if
  the exit status is at least 2 if the error occurred while running
  the test builtin.
- b_test(): Set sh_in_test_builtin flag while running test builtin.

src/cmd/ksh93/sh/arith.c,
src/cmd/ksh93/sh/streval.c:
- Override ERROR_exit macro using function from test.c.

src/cmd/ksh93/tests/bracket.sh:
- Add regression test verifying status > 1 on arith error in test.

(cherry picked from commit 5eeae5eb9fd5ed961a5096764ad11ab870a223a9)
2020-06-12 01:45:15 +02:00
Martijn Dekker
e902633abe bin/shtests: fix SHELL=/path/to/ksh assignment argument
Passing a SHELL=/path/to/ksh assignment-argument after the
bin/shtest command (as documented in 'shtest --man') made the
wrapper script produce inconsistent results: it would launch and
claim to test the default shell, but src/cmd/ksh93/tests/shtests
would actually test the shell indicated in the argument.

bin/shtests:
- Scan arguments for a SHELL= (or KSH=) assignment-argument,
  setting $KSH (and then exporting $SHELL) based on that if found.

(cherry picked from commit 1e78fbbd094dfc84989ecadf06231c6515fb7412)
2020-06-12 01:45:14 +02:00
Martijn Dekker
ec888867fd 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-06-12 01:45:14 +02:00
Martijn Dekker
047cb3303c 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-06-12 01:45:14 +02:00
Martijn Dekker
6e90d4d76c tests/path.sh: if root, skip tests involving unreadable scripts
These always fail when running as root, as root can access files
regardless of permission bits.

(cherry picked from commit a821fe13906ac8ef56162bebd7c3e976b973f91c)
2020-06-12 01:45:14 +02:00
Martijn Dekker
62f8e744f1 tests/variables.sh: minor fix in failure error msg
(cherry picked from commit bdcbcf42415aaf120a4e3a98fd4af1f8b810018f)
2020-06-12 01:45:14 +02:00
Martijn Dekker
593a5a8b7f Patch vulnerability CVE-2019-14868
Certain environment variables were interpreted as arithmetic
expressions on startup, leading to code injection.

Ref.:
https://bugzilla.redhat.com/show_bug.cgi?id=1757324
c7de8b6412

(cherry picked from commit ee6b001d0611ad2e00b6da2c2b42051995c0a678)
2020-06-12 01:45:14 +02:00
Martijn Dekker
c1dae413d2 shtests: don't require specifying .sh extension for test script
It was annoying me that I always had to type out the .sh in
'shtests builtins.sh', etc. to execute a specific regression test
script. All the test scripts end in .sh, so this is superflous.

src/cmd/ksh93/tests/shtests:
- Add .sh to test script arguments if not already present.

(cherry picked from commit d780e701fbf6f27b6e79f88542a3175bf5dd85e9)
2020-06-12 01:45:14 +02:00
Martijn Dekker
e999f6b169 Fix truncating of files with <>;file combined with <#pattern
The issue with truncating files was caused by out-of-sync streams.
Details and discussion: https://github.com/att/ast/issues/61

src/cmd/ksh93/sh/io.c: sh_iorestore():
- To be safe, sync all streams before restoring file descriptors.

src/cmd/ksh93/tests/io.sh:
- Add two regression tests for truncating files with this
  combination of redirections.
- The second test, which invokes a -c script, is disabled for now
  as this triggers another corner case bug involving the SH_NOFORK
  optimisaton for -c scripts. That fix is for another commit.

(cherry picked from commit 18fb64840365c2ff4608188e5487bd79d08f67d1)
2020-06-12 01:45:14 +02:00
Martijn Dekker
a638e724d0 INIT/cc.darwin: revert inadvertent change in SHOPT_SPAWN
(cherry picked from commit def69c3315d1d357b3e067a186913991ea2abdf3)
2020-06-12 01:45:14 +02:00
Martijn Dekker
60516872de tests/io.sh: Update after BUG_PUTIOERR and BUG_REDIRIO fixes
src/cmd/ksh93/tests/io.sh:
- After BUG_REDIRIO was fixed in 29afc16c, '<>' now defaults to
  '0<>' instead of '1<>', as POSIX specifies. Update '<>' to '1<>'.
- After BUG_PUTIOERR was fixed in 9011fa93, one 'print' command
  with pipe buffering disabled (piped into 'read -n3') printed an
  expected I/O error to standard error. Redirect this to /dev/null.

(cherry picked from commit d4b6510fdf155a3d75a98860a09c0ebedb6c93d2)
2020-06-12 01:45:14 +02:00
Martijn Dekker
952944197f 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-06-12 01:45:14 +02:00
Martijn Dekker
2887378ae3 INIT/cc.darwin: suppress another annoying compiler warning
src/cmd/INIT/cc.darwin:
- Since the flags added from Apple's ksh-27.tar.gz Makefile
  explicitly redefine a macro, let's disable the warning on
  redefined macros.

(cherry picked from commit 4b21a0abce8406e82d3afa4a68ef6bb56d98c797)
2020-06-12 01:45:14 +02:00
Martijn Dekker
c9ccee86bb Fix 'command -p' by fixing initialisation of default PATH variable
'command -p' was broken for non-interactive shells as the variable
used to store the default system PATH, std_path, was not
initialised correctly. For instance:
	$ ksh -c 'command -p ls'
	ksh: ls: not found
This fix by Siteshwar Vashisht is backported from ksh2020.
Ref.:
https://github.com/att/ast/issues/426
https://github.com/att/ast/pull/448

src/cmd/ksh93/sh/path.c:
- Correctly initialise std_path (the default PATH) when ksh is
  started as a non-interactive shell.

src/cmd/ksh93/sh.1:
- Fix vague explanation of 'command -p'.

src/cmd/ksh93/tests/path.sh:
- Add regression test.

(cherry picked from commit a76439d60b70c18cf44d84c1962fcd8df84c947c)
2020-06-12 01:45:14 +02:00
Martijn Dekker
f35e7ecd1d INIT/cc.darwin: default to -Os (small code) like Apple does
(cherry picked from commit 2210ff9026ca3f05dc88988c72f56eea195753cc)
2020-06-12 01:45:14 +02:00
Martijn Dekker
9f6dd1ea73 ksh93/sh.1: say that ${.sh.subshell} only counts virtual subshells
${.sh.subshell} only counts the nesting level of virtual (non-forked)
subshell environments relative to the current process, whether that
is the main shell environment or a real (forked) subshell.

This means ${.sh.subshell} is not sufficient to test if your code
is running in a subshell environment, so it's important to mention
this in the manual.

E.g.:
    (echo ${.sh.subshell}; ulimit -t 1; echo ${.sh.subshell}); :
outputs 1 followed by 0.

(cherry picked from commit 63dad8863fd26bf3aa4d7a1cf60b743f4169f7c4)
2020-06-12 01:45:14 +02:00
Martijn Dekker
d10eab988a Regression test suite: bugfix: accurately report number of errors
The number of errors in each tests/*.sh test set is reported using
its exit code (up to 125). The main test script saves this code in
$e to report the number of errors. But if a set had errors, $e was
then erroneously overwritten before reporting the number of errors,
so it was always 1.

src/cmd/ksh93/tests/shtests:
- Don't overwrite $e with the exit code of ((e == 0)).

(cherry picked from commit b9ab95488b23167316f5b21f338368c9490ebc50)
2020-06-12 01:45:14 +02:00
Martijn Dekker
75fc493e7d sh/suid_exec.c: fix 2 confusing typos in comments
(cherry picked from commit 6cccaedd91e4309b542b8a17c8318f3bff9511b0)
2020-06-12 01:45:14 +02:00
Martijn Dekker
412cd96dc1 fix 5 more typos: incorrect "than"
(cherry picked from commit 7e2e4651d2dd5884dd3ea06fc8df4dc45ec9bfb5)
2020-06-12 01:45:13 +02:00