1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00
Commit graph

617 commits

Author SHA1 Message Date
Martijn Dekker
4dcf5c5066 Apply patches to build on DragonFly BSD and (older) FreeBSD
This now makes ksh build on DragonFly BSD.

bin/package, src/cmd/INIT/package.sh:
- DragonFly also needs the -lm hack for LDFLAGS.

src/cmd/ksh93/sh/main.c, src/cmd/ksh93/tests/basic.sh:
- fixargs() doesn't work on DragonFly either
  (re: 9b7c392a, 159fb9ee, cefe087d).

The following are backported from:
https://github.com/att/ast/issues/26#issuecomment-313927854
https://github.com/att/ast/pull/19

src/lib/libast/comp/setlocale.c:
- Add missing #include <errno.h> since errno is used.

src/lib/libast/features/standards:
- Do not set any standards macros (_POSIX_SOURCE etc) on FreeBSD or
  DragonflyBSD; they disable too much functionality on those.

src/lib/libast/features/wchar:
- Set _STDFILE_DECLARED on DragonFly, too.

src/lib/libast/include/sfio.h, src/lib/libast/include/sfio_t.h,
src/lib/libast/sfio/_sfopen.c, src/lib/libast/sfio/sfclrlock.c,
src/lib/libast/sfio/sfhdr.h, src/lib/libast/sfio/sfnew.c,
src/lib/libast/sfio/sfset.c:
- Rename SF_* macros to SFIO_* to avoid a conflict with system
  headers.

src/lib/libast/string/strexpr.c:
- Rename error() to err() to avoid a conflict.
2021-01-18 09:08:48 +00:00
Martijn Dekker
8633290e63 Fix build failure on certain versions of glibc
Patch from:
https://bugzilla.redhat.com/show_bug.cgi?id=1477082

See also:
https://github.com/att/ast/pull/63
https://bugs.debian.org/887743
2021-01-18 07:48:15 +00:00
Martijn Dekker
8361e065e6 job_unpost(): fix segfault
This function could segfault under certain conditions (in macOS
Terminal, when ksh received SIGWINCH and a complex PS1 prompt is
defined; see 61437b27)

0   ksh            job_unpost + 49 (jobs.c:1703)
1   ksh            job_reap + 1632 (jobs.c:468)
2   ksh            job_wait + 942 (jobs.c:1525)
3   ksh            sh_exec + 19579 (xec.c:1627)
4   ksh            sh_eval + 545 (xec.c:763)
5   ksh            sh_trap + 427
6   ksh            ed_emacsread + 3598 (emacs.c:1072)
7   ksh            slowread + 489 (io.c:1962)
8   ksh            sfrd + 1026 (sfrd.c:253)
9   ksh            _sffilbuf + 587 (sffilbuf.c:105)
10  ksh            sfreserve + 662
11  ksh            exfile + 1922 (main.c:527)
12  ksh            sh_main + 1071 (main.c:351)
13  libdyld.dylib  start + 1

src/cmd/ksh93/sh/jobs.c: job_unpost():
- Fix a dereference of a possible null pointer returned by
  job_byjid(). Add a check and return if that pointer is null.
2021-01-18 07:14:06 +00:00
Martijn Dekker
7222ba3af7 tests/basic.sh: fix intermittent spurious regress fail
~- and ~+ are ksh93-specific tilde expansions that expand to
$OLDPWD and $PWD, respectively. On some systems, $OLDPWD is not set
on entry to the test script, because it is not exported to the
environment. This made it unset before any 'cd' was executed,
which (correctly) disabled ~- expansion.

src/cmd/ksh93/tests/basic.sh:
- Before testing 'cd ~-', make sure $OLDPWD is set by cd'ing to
  /dev first (a directory guaranteed by POSIX).
2021-01-18 06:27:08 +00:00
Martijn Dekker
8e8ff5f6f6 Disable SHOPT_PFSH in feature test (re: f089d799)
src/cmd/ksh93/features/options:
- To make sure SHOPT_PFSH stays disabled on Solaris, we
  also need to stop this feature test from re-enabling it.
2021-01-18 06:11:45 +00:00
Martijn Dekker
f089d7990a Solaris: disable deprecated SHOPT_PFSH by default
Solaris /bin/ksh disables the SHOPT_PFSH compile option ("solaris
exec_attr(4) profile execution") with a patch. Since this option
applies to Solaris and variants only, let's upstream that change.

(Solaris now provides pfksh93 as a wrapper around ksh93, and does
the same for other shells, so profiling functionality is no longer
ksh-specific.)

If you want to re-enable it, add -DSHOPT_PFSH to your $CCFLAGS.

Original patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/150-CR7168611.patch

src/cmd/ksh93/Makefile:
- Add note that edits in Makefile are ineffective as we do not ship
  nmake.
- Disable SHOPT_PFSH, cosmetically.

src/cmd/ksh93/Mamfile:
- Remove -DSHOPT_PFSH from all compiler commands.
2021-01-18 05:29:09 +00:00
Martijn Dekker
4cfe49aebb package: involve $CCFLAGS when determing 64-bit arch (re: 9a48ba15)
bin/package, src/cmd/INIT/package.sh:
- It can depend on the compiler flags passed whether the compiler
  produces code for a 64-bit architecture, so pass $CCFLAGS to
  the compiler when testing whether it creates 64-bit object code.

README.md:
- Copy-edit of build instructions.
2021-01-18 03:56:03 +00:00
Martijn Dekker
580ff61617 Fix release and standards build flags (re: 35672208, aa4669ad)
bin/package, src/cmd/INIT/package.sh:
- CCFLAGS overwrites the autodetected optimisation flags (e.g. -Os)
  if set. Unfortunately, that also happened when we added something
  to CCFLAGS for a release build or to add an extra flag needed by
  Solaris. The fix is to use a new flags variable (KSH_RELFLAGS)
  instead. This needs to be done in a different place as it needs
  to be added to the mamake command as an assignment argument.
- Remove the Solaris CCFLAGS hack; see features/common below.

src/*/*/Mamfile:
- Add ${KSH_RELFLAGS} to all the compiler commands.

src/lib/libast/features/common:
- Enable POSIX standard on Solaris (i.e.: if __sun is defined) by
  defining _XPG6 directly in the feature test that generates
  ast_std.h, which is indirectly included by everything. This
  removes the need to pass -D_XPG6 via CCFLAGS. (Doing so
  automatically with gcc was not otherwise possible.)

src/cmd/INIT/cc.sol11.*:
- No longer pass -D_XPG6, as per above.
2021-01-18 01:07:45 +00:00
Martijn Dekker
e25d9f4190 nv_newattr(): fix potential invalid free
src/cmd/ksh93/sh/name.c:
- Zero the 'cp' pointer after freeing it, as the next loop
  iteration may otherwise re-use the old address.
2021-01-17 03:55:46 +00:00
Martijn Dekker
9a48ba1557 package: fix code for detecting 64-bit compiler
bin/package, src/cmd/INIT/package.sh:
- The code for detecting a 64-bit object file was seriously broken:
  the temporary file name could contain '64' because it included $$,
  the current PID, and 64-bit was detected if the output of 'file'
  (which includes the complete file name) contained '64'. Fix by
  removing the file name from 'file' output before testing.
- Also refactor that code a bit and remove the nonsensical test if
  /bin/sh is a 64-bit binary, which is neither here nor there. It's
  what the compiler produces that we need to care about.
2021-01-16 22:53:35 +00:00
Martijn Dekker
6025c8125e make.probe: add fallback optimisation flags
src/cmd/INIT/make.probe:
- probe_optimize: Also try -O2 and -O, for compilers (such as
  Solaris Studio cc) that do not support -Os.
- Use more robust code to loop through possible optimiser flags.
2021-01-16 22:01:07 +01:00
Martijn Dekker
1554ec2cdd libast: Revert conf.sh changes (re: 2e839d87, 3aa01a95)
These caused a compilation failure in the generated conftab.c
file while compiling on Solaris with gcc.
2021-01-16 19:27:48 +01:00
Martijn Dekker
68a6f9a6e2 Fix Solaris cc wrappers (re: 4e67234a)
The versions from the Solaris patch require $CC_EXPLICIT to be set,
which is specific to the internal Solaris build environment.

src/cmd/INIT/cc.sol11.*:
- Cope without $CC_EXPLICIT set in environment; fall back to $CC
  and if that is not set either, detect whether to use cc or gcc.
- Set appropriate flags for cc (Solaris Studio) or gcc, including
  the necessary -D_XPG6 flag, without which ksh crashes on Solaris.

bin/package, src/cmd/INIT/package.sh:
- Update hack to add the -D_XPG6 flag so it applies to gcc only
  (note: the src/cmd/INIT/cc.* scripts are never used for gcc).
2021-01-16 19:25:39 +01:00
Martijn Dekker
2e839d8775 getconf detection: fix compiler error msg extraction (re: 3aa01a95)
That patch didn't work for non-gcc, non-clang compilers -- at least
Solaris Studio cc. It doesn't prefix error messages with "error:".
As a result, it caused the build to fail on Solaris with native cc.

src/lib/libast/comp/conf.sh:
- Use a sed formula that should catch error messages prefixed by
  "line xx:" while still removing warnings and suggestions. This
  works on at least clang, gcc, Solaris Studio cc.
2021-01-16 14:43:22 +00:00
Martijn Dekker
2f7918deec libast: backport tvsleep(3) from ksh 93v- (re: 2db9953a)
src/lib/libast/tm/tvsleep.c:
- Since the 'sleep' builtin was backported/fixed from ksh93v- and
  ksh2020, it makes sense to use the latest/last tvsleep(3), too.
  Looks like this added an interrupt check (errno == EINTR).
  Also, new fallback versions for systems without nanosleep(2).

Documentation: src/lib/libast/man/tv.3 (unchanged)
2021-01-15 19:05:32 +00:00
Martijn Dekker
a3f4ef7adf libast: fix detection of long double NaN/INF signatures
src/lib/libast/features/float:
- libast attempts to determine the binary representation of Inf and
  NaN to use as a fall-back code path for systems that do not
  support fpclassify(). The libast feature detection did not get
  consistent signatures between builds. To fix this, zero the
  memory before determining the signature.

src/lib/libast/sfio/sfcvt.c:
- The fall-back code path is broken because there are multiple
  representations for NaN - the important thing is to check the
  exponent and for a non-zero significand. The trailing bits can be
  random or left over from interim operations. For that reason, to
  ensure we never end up using the fall-back code path, explicitly
  generate a compile error if we end up there.

Based on a patch from @citrus-it:
8bf59a9a8f
but uses POSIX memset(3) instead of deprecated bzero(3).
2021-01-15 15:40:12 +00:00
Martijn Dekker
3aa01a95ee getconf detection: cope with new compiler messages
conf.sh checks for undefined symbols by parsing compiler output and
looking for strings of capital letters and underscores. Modern gcc
produces suggestions for replacement variables too, for example:

error: '_SC_CLOCKRES_MIN' undeclared here (not in a function); did you mean _POSIX_CLOCKRES_MIN?
 _SC_CLOCKRES_MIN,
 ^~~~~~~~~~~~~~~~
 _POSIX_CLOCKRES_MIN

This causes good variables to be excluded along with bad, causing differences
between the builtin and system getconf commands.

src/lib/libast/comp/conf.sh:
- Only use lines containing 'error:' and ignore everything starting
  from 'did you mean:'. (Note this scripts sets the locale to C.)

Patch from @citrus-it:
061a4b1da1
2021-01-15 15:38:14 +00:00
Martijn Dekker
649f4b047b tests/builtins.sh: tweak for HP-UX 2021-01-12 18:18:39 +00:00
Martijn Dekker
4d5e21de80 Fix for compiling with SHOPT_DYNAMIC disabled
src/cmd/ksh93/bltins/typeset.c:
- Correct faulty preprocessor directive logic causing a build
  failure if SHOPT_DYNAMIC is disabled.
2021-01-10 23:02:15 +00:00
Martijn Dekker
e981f7c8b8 Regression test tweaks to avoid false fails on Solaris
src/cmd/ksh93/tests/path.sh:
- Re-export PATH after unsetting it.

src/cmd/ksh93/tests/pty.sh:
- Increase some delays.
2021-01-10 20:53:41 +01:00
Martijn Dekker
9b7c392a7c Disable fixargs() on Solaris (re: 159fb9ee, cefe087d)
It doesn't work on Solaris either.
2021-01-10 18:47:12 +00:00
Martijn Dekker
159fb9ee27 main.c: Tweak fixargs() (re: cefe087d)
src/cmd/ksh93/sh/main.c: fixargs():
- Erase the entire length of the command arguments buffer (the
  space from argv[0] until environ[0]) so that remnants of longer
  command arguments aren't left in 'ps' output when executing a
  hashbang-ess script with a shorter command line.
- Disable fixargs() on FreeBSD. It has never had any effect on that
  system; apparently it either requires another method to rewrite
  arguments for 'ps' output purposes (which?) or it's not possible.

src/cmd/ksh93/tests/basic.sh:
- Skip the test if running on FreeBSD.
2021-01-10 06:34:49 +00:00
Martijn Dekker
e7202832fd Revert "bin/package: don't test-compile using possibly broken dev shell"
This reverts commit 600cb182.
$cc may be a system compiler binary, it is not necessarily a
src/cmd/INIT/cc.* wrapper script; so prefixing 'sh' is wrong.
2021-01-09 16:16:28 +00:00
Martijn Dekker
4d0b77d398 Revert "Fix SIGALRM core dump (Solaris patch 230-18229654)"
This reverts commit 13e7b262. It caused the regression test for the
'alarm' builtin, introduced in 18b3f4aa, to hang on FreeBSD.
2021-01-09 13:18:00 +00:00
Martijn Dekker
7d2bb8fdd9 libast: fix exec fail on interactive (Solaris patch 315-26773587)
This upstreams a Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/315-26773587.patch
which ostensibly fixes this bug filed in Oracle's closed system:
26773587 interactive ksh exec failure in while read loop

src/lib/libast/comp/spawnveg.c:
- If posix_spawn(3) fails with an error other than EPERM, retry,
  but without attributes.
2021-01-09 01:58:23 +00:00
Martijn Dekker
4e67234ae8 INIT: Add Solaris 11 compiler wrappers (Solaris patch 005-compiler)
This upstreams a Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/005-compiler.patch
2021-01-09 01:03:08 +00:00
Martijn Dekker
e03c010c4d Fix for non-UTF-8 wide charsets (Solaris patch 050-CR7065478)
This upstreams a Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/050-CR7065478.patch

src/lib/libast/comp/setlocale.c:
- Add wide_wctomb() wrapper for wctomb(3). It changes an invalid
  character (wctomb returns -1) to a single byte with length 1.
- set_ctype(): Use wide_wctomb() instead of wctomb(3) as the
  conversion discipline function (ast.mb_conv). Effectively this
  means there are no invalid characters. Perhaps this is necessary
  for compatibility with ASCII. Sadly, no public info available.
2021-01-09 00:45:51 +00:00
Martijn Dekker
096f46eee5 Fix for memory mgmt in variable expansion (Solaris 105-CR7032068)
This upstreams a Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/105-CR7032068.patch

No other information is publicly available but this has been in
production use on Solaris for a long time. It looks like this is
intended to avoid an invalid free().
2021-01-09 00:28:11 +00:00
Martijn Dekker
37637ab6b4 libast: sfmode: tweak for 64-bit (Solaris 140-MAP_TYPE_64_Bits)
This upstreams a Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/140-MAP_TYPE_64_Bits.patch

src/lib/libast/sfio/sfmode.c: _sfmode():
- Do not turn off mmap on 64-bit systems.
2021-01-09 00:06:13 +00:00
Martijn Dekker
aa7713c2a9 sh_init(): rm directoryless '.profile' login file path
This applies a patch from Solaris:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/160-CR7175995.patch

There is no public information on why it's needed, but it seems
sensible on the face of it. Using a file called '.profile' in the
PWD on login, without a directory path, is redundant at best, since
"$HOME/.profile" (e_profile, see data/msg.c) is already used. And
if the PWD is not $HOME at login time, it seems to me there are
serious problems and the last thing you want is to read some
random and probably dodgy '.profile' from the PWD.

src/cmd/ksh93/sh/init.c: sh_init(): login_files[]:
- Remove redundant/problematic ".profile" entry.
2021-01-08 23:53:04 +00:00
Martijn Dekker
5d7e00a109 cd: validate $OLDPWD (Solaris patch 185-Bug17714341)
This change was pulled in from:
https://raw.githubusercontent.com/oracle/solaris-userland/master/components/ksh93/patches/185-Bug17714341.patch

No public information about the reasons for this change is
available, but it seems reasonable to trust that the Solaris people
found a legitimate need for it.

src/cmd/ksh93/bltins/cd_pwd.c: b_cd():
- When determining the old PWD before 'cd', do not trust shp->pwd
  but get and validate the current PWD using path_pwd().
2021-01-08 22:31:16 +00:00
Martijn Dekker
1de20d65a8 Fix crash on long PS1 prompt (Solaris patch 195-17824699)
Original report and info:
https://www.mail-archive.com/ast-developers@lists.research.att.com/msg01677.html
https://www.mail-archive.com/ast-developers@lists.research.att.com/msg01679.html

Patch pulled in from:
https://raw.githubusercontent.com/oracle/solaris-userland/master/components/ksh93/patches/195-17824699.patch

src/cmd/ksh93/edit/edit.c: ed_setup():
- Prevent the ed_setup() function from writing past ep->e_prompt,
  which is set to the local char prompt[PRSIZE] variable in
  ed_emacsread().

src/cmd/ksh93/include/edit.h:
- Increase maximum prompt size, PRSIZE, to 256.
2021-01-08 22:22:47 +00:00
Martijn Dekker
86fc4c6d0a init: Refuse to import $KSH_VERSION from environment
$KSH_VERSION is initialised as a nameref to ${.sh.version}, but it
was not realiable as it could be overridden from the environment.
Some scripts do version checking so this would allow influencing
their execution.

This fix is inspired by the following Solaris patch:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/200-17435456.patch
but a different approach was needed, because the code has changed
(see 960a1a99).

src/cmd/ksh93/sh/init.c: env_init():
- Refuse to import $KSH_VERSION. Using strncmp(3) might be crude,
  but it's effective and I can't figure out another way.
2021-01-08 21:59:30 +00:00
Martijn Dekker
13e7b26202 Fix SIGALRM core dump (Solaris patch 230-18229654)
This should fix the following Solaris bug:
18229654 ksh93 read not reentrant in alarm context dumps core
with the patch taken from:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/230-18229654.patch

Unfortunately the link to the details is inaccessible
as lists.research.att.com is dead.
2021-01-08 18:50:34 +00:00
Martijn Dekker
99cbb7f794 Add reproducer from https://github.com/att/ast/issues/7 as regress
ksh 93u+ has a subshell leak bug where a variable exported in
function in a subshell is also visible in a different subshell.
This is long fixed in 93u+m, but there wasn't a regression test for
this particular bug yet, so this commit adds one.
2021-01-08 18:15:11 +00:00
Martijn Dekker
62cf88d0df Fix SIGHUP on termination (Solaris patch 260-22964338)
This fixes the following bug filed with Solaris: "22964338 ksh93
appears to send SIGHUP to unrelated processes on occasion". It is
fixed by applying this patch by Lijo George from the Solaris repo:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/260-22964338.patch

The ksh2020 upstream rejected this, but if it's in production use
in Solaris, Solaris, it's probably good enough for 93u+m. If any
breakage is left, it can be fixed later.
https://github.com/att/ast/pull/1

src/cmd/ksh93/include/jobs.h,
src/cmd/ksh93/sh/fault.c,
src/cmd/ksh93/sh/jobs.c:
- Use a new job_hup() function instead of job_kill() to send SIGHUP
  to job processes on termination. The new function checks if a job
  is in fact still live before issuing SIGHUP to it.
2021-01-08 17:33:04 +00:00
Martijn Dekker
ab98ec65e4 Replace safe FD fix with Solaris/ksh2020 version (re: 045fe6a1)
This pulls a new version of sh_iosafefd() from:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/285-30771135.patch

It was written by Kurtis Rader for ksh2020:
https://github.com/att/ast/issues/198
https://github.com/att/ast/pull/199
It is presumably better than the Red Hat version and also comes
with more regression test cases (although it still doesn't fix
modernish BUG_CSUBSTDO, which remains in the TODO file).

This commit does not go along with other peripheral changes from
that patch, i.e. a different name and location of this function.

src/cmd/ksh93/sh/io.c:
- Replace sh_iosafefd() as above.

src/cmd/ksh93/tests/subshell.sh:
- Add and tweak tests from the patch.
2021-01-08 16:35:26 +00:00
Martijn Dekker
17ebfbf6a3 Fix I/O redirection in -c script (Solaris patch 280-23332860)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/280-23332860.patch

Info and reproducers:
https://github.com/att/ast/issues/36

In a -c script (like ksh -c 'commands'), the last command
misredirects standard output if an EXIT or ERR trap is set.
This appears to be a side effect of the optimisation that
runs the last command without forking.

This applies a patch by George Lijo that flags these specific
cases and disables the optimisation.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/bltins/trap.c,
src/cmd/ksh93/sh/init.c,
src/cmd/ksh93/sh/main.c,
src/cmd/ksh93/sh/xec.c:
- Apply patch as above.

src/cmd/ksh93/tests/io.sh:
- Add the reproducers from the bug report as regression tests.
2021-01-08 15:15:53 +00:00
Martijn Dekker
7c47ab56fe I/O: Properly handle EIO error (Solaris patch 275-20855453)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/275-20855453.patch
https://github.com/att/ast/issues/30

George Lijo wrote on 17 Feb 2017:
> Here's a reproducible testcase on a Solaris11 host running
> ksh93u+(2012-08-01).
> $ cat a.sh
> #!/bin/sh
>
> AAA="aaa"
> echo 'insert character'
> BBB=`echo ${AAA} | sed "s/aaa/bbb/g"`
> logger "variable BBB = ${BBB}"
>
> $ cat t.sh
> #!/bin/ksh
>
> sleep 10
> /bin/ksh ./a.sh
> exit 0
>
> $
>
> $ ./t.sh
>
> The expected result is:
>
> Apr 9 12:43:34 lab user: [ID 702911 user.notice] variable BBB = bbb
>
> because variable "BBB" is supposed to be set to 'bbb' in a.sh.
>
> But if the parent shell is terminated, the variable is wrongly set.
>
> user@xxxxx$ telnet lab
> ...
> $ ./t.sh & <--- Run t.sh in background.
> [1] 2067
> $ logout <--- CTRL + D to exit while t.sh is running.
> Connection to lab closed by foreign host.
>
> Again, access the system and check the output:
>
> user@xxxxx$ telnet lab
> ...
> $ tail -f /var/adm/messages
> :
> Apr 9 12:47:47 lab user: [ID 702911 user.notice] variable BBB =
> insert character <--- !!!
> Apr 9 12:47:47 lab bbb
> <--- !!!
>
> Thus the variable is wrongly set. (The previous echo string was
> not cleared.)
>
> The issue happens because the EIO error during the logout is not
> handled properly.

src/cmd/ksh93/sh/io.c,
src/lib/libast/include/error.h:
- Amend the ERROR_PIPE() macro to check for EIO as well as EPIPE
  and ECONNRESET.
2021-01-08 13:28:45 +00:00
Martijn Dekker
3f38f8a285 emacs: Fix crash on inputting Asian chars (Solaris 240-22461939)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/240-22461939.patch

Information:
https://github.com/att/ast/issues/6

George Lijo wrote on 14 Mar 2016:
> I observed this issue in a Solaris 11 system on ksh2012-08-01
> [...]. The issue can be reproduced if we add Asian locales to
> ibus (such as Korean). In the ksh93 shell prompt, input some
> Asian character. ksh promptly dumps core [...].
>
> The coredump happens at the following line no 320 in
> src/cmd/ksh93/edit/emacs.c
>	if(c!='\t' && c!=ESC && !isdigit(c)).
>
> I referred the vi.c code and added the digit(c) macro, i.e.
> ((c&~STRIP)==0 && isdigit(c)) and replaced the isdigit(c) usage
> with the "digit(c)" macro.
2021-01-08 12:55:05 +00:00
Martijn Dekker
a3ccff6c75 cd: fix an invalid free() call (Solaris patch 211-21547336)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/211-21547336.patch

src/cmd/ksh93/bltins/cd_pwd.c: b_cd():
- The functions path_pwd() and path_relative() in sh/path.c may
  return a pointer to e_dot[] (".") as a fallback if they fail to
  determine a path. This is a string in read-only memory
  (data/msg.c), so must not be freed. A pointer to that string may
  end up in sh.pwd (== shp->pwd), so b_cd() needs a check for that.
2021-01-08 12:43:19 +00:00
Martijn Dekker
ad9ea0ba7d Fix off-by-one in nv_mktype() (Solaris patch 210-Bug15993811)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/210-Bug15993811.patch

Unfortunately there is no publicly available documentation on why
this change was needed. We just have to assume the Solaris people
knew what they were doing. ksh2020 upstreamed this too (as well as
all the other Solaris patches applied here).
2021-01-08 11:56:04 +00:00
Martijn Dekker
ba4989d974 libast/port/mnt.c: rm cachefs support (Solaris patch 135-CR6729252)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/135-CR6729252.patch
2021-01-08 11:50:57 +00:00
Martijn Dekker
744e68e7be rm obsolete /usr/5bin paths (Solaris patch 130-CR7019368)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/130-CR7019368.patch
2021-01-08 11:47:05 +00:00
Martijn Dekker
bae02c39b6 Fix for argv for setuid scripts (Solaris patch 115-CR6934836)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/115-CR6934836.patch

Unfortunately there is no publicly available documentation on what
this does or why it was needed. We just have to assume the Solaris
people knew what they were doing. ksh2020 upstreamed this too (as
well as all the other Solaris patches applied here).
2021-01-08 11:28:33 +00:00
Martijn Dekker
3f15067272 setdisc(): Return null pointer if no event (Solaris 110-CR7061011)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/110-CR7061011.patch

Unfortunately there is no publicly available documentation on why
this change was needed. We just have to assume the Solaris people
knew what they were doing. ksh2020 upstreamed this too (as well as
all the other Solaris patches applied here).

src/cmd/ksh93/sh/nvdisc.c: setdisc():
- If no <event> is known for <np>, return a null pointer instead
  of a pointer to the empty string.
2021-01-08 11:27:30 +00:00
Martijn Dekker
54c4e94205 Fix for libast sfstrtof() (Solaris patch 075-multi_lang_arith)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/075-multi_lang_arith.patch

It appears to be a fix for converting a string to a floating point
value in certain locales. Unfortunately there is no publicly
available documentation on what it does exactly. We just have to
assume the Solaris people knew what they were doing.
2021-01-08 05:30:29 +00:00
Martijn Dekker
c69bf543cf libcmd/wclib: Fix for wide char handling (Solaris 055-CR7026179)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/055-CR7026179.patch

It's a fix for wide-character handling in the wc (word count)
library.
2021-01-08 05:20:28 +00:00
Martijn Dekker
4c75920baa libcmd/cmp: report read errors (Solaris patch 045-CR7025778)
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/045-CR7025778.patch

src/lib/libcmd/cmp.c:
- If a read error occurs, issue an error message.
2021-01-08 05:13:02 +00:00
Martijn Dekker
e20db01247 Apply Solaris patch 065-CR7110983
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/065-CR7110983.patch

Unfortunately there is no publicly available documentation on what
it does. We just have to assume the Solaris people knew what they
were doing. It looks like this fixes a memory leak in nv_putval().

This patch was also applied by ksh2020:
056386400a
2021-01-08 04:59:54 +00:00
Martijn Dekker
222515bf08 Implement hash tables for virtual subshells (re: 102868f8, 9d428f8f)
The forking fix implemented in 102868f8 and 9d428f8f, which stops
the main shell's hash table from being cleared if PATH is changed
in a subshell, can cause a significant performance penalty for
certain scripts that do something like

    ( PATH=... command foo )

in a subshell, especially if done repeatedly. This is because the
hash table is cleared (and hence a subshell forks) even for
temporary PATH assignments preceding commands.

It also just plain doesn't work. For instance:

    $ hash -r; (ls) >/dev/null; hash
    ls=/bin/ls

Simply running an external command in a subshell caches the path in
the hash table that is shared with a main shell. To remedy this, we
would have to fork the subshell before forking any external
command. And that would be an unacceptable performance regression.

Virtual subshells do not need to fork when changing PATH if they
get their own hash tables. This commit adds these. The code for
alias subshell trees (which was removed in ec888867 because they
were broken and unneeded) provided the beginning of a template for
their implementation.

src/cmd/ksh93/sh/subshell.c:
- struct subshell: Add strack pointer to subshell hash table.
- Add sh_subtracktree(): return pointer to subshell hash table.
- sh_subfuntree(): Refactor a bit for legibility.
- sh_subshell(): Add code for cleaning up subshell hash table.

src/cmd/ksh93/sh/name.c:
- nv_putval(): Remove code to fork a subshell upon resetting PATH.
- nv_rehash(): When in a subshell, invalidate a hash table entry
  for a subshell by creating the subshell scope if needed, then
  giving that entry the NV_NOALIAS attribute to invalidate it.

src/cmd/ksh93/sh/path.c: path_search():
- To set a tracked alias/hash table entry, use sh_subtracktree()
  and pass the HASH_NOSCOPE flag to nv_search() so that any new
  entries are added to the current subshell table (if any) and do
  not influence any parent scopes.

src/cmd/ksh93/bltins/typeset.c: b_alias():
- b_alias(): For hash table entries, use sh_subtracktree() instead
  of forking a subshell. Keep forking for normal aliases.
- setall(): To set a tracked alias/hash table entry, pass the
  HASH_NOSCOPE flag to nv_search() so that any new entries are
  added to the current subshell table (if any) and do not influence
  any parent scopes.

src/cmd/ksh93/sh/init.c: put_restricted():
- Update code for clearing the hash table (when changing $PATH) to
  use sh_subtracktree().

src/cmd/ksh93/bltins/cd_pwd.c:
- When invalidating path name bindings to relative paths, use the
  subshell hash tree if applicable by calling sh_subtracktree().
- rehash(): Call nv_rehash() instead of _nv_unset()ting the hash
  table entry; this is needed to work correctly in subshells.

src/cmd/ksh93/tests/leaks.sh:
- Add leak tests for various PATH-related operations in the main
  shell and in a virtual subshell.
- Several pre-existing memory leaks are exposed by the new tests
  (I've confirmed these in 93u+). The tests are disabled and marked
  TODO for now, as these bugs have not yet been fixed.

src/cmd/ksh93/tests/subshell.sh:
- Update.

Resolves: https://github.com/ksh93/ksh/issues/66
2021-01-07 22:18:25 +00:00
Martijn Dekker
a95d107ee5 Fix segfault while updating ${.sh.match}
The SHOPT_2DMATCH code block in sh_setmatch() modifies the 'ap'
pointer, which is initialised as nv_arrayptr(SH_MATCHNOD). This
caused a (rarely occurring) segfault in the following line near the
end of the function:
	ap->nelem -= x;
as this line assumed that 'ap' still had the initial value.

src/cmd/ksh93/sh/init.c: sh_setmatch():
- On init, save ap in ap_save and use ap_save instead of ap where
  it should be pointing to SH_MATCHNOD. This also allows removing
  two redundant nv_arrayptr(SH_MATCHNOD) calls, slightly increasing
  the efficiency of this function.
2021-01-07 17:34:47 +00:00
Martijn Dekker
c8513fcb7a Arith: informative err msg on '.' radix point in non-'.' locales
Scripts that use floating point shell arithmetic confusingly fail
with 'arithmetic syntax error' when running in a locale that uses
',' as the radix point, because '.' is generally assumed by
scripts. The error message is confounding as the problem is not a
syntax error but a locale that is incompatible with the script.

src/cmd/ksh93/sh/arith.c:
- If the locale's radix point is not '.' but a '.' is found in its
  place, issue an informative error message that instructs setting
  LC_NUMERIC=C.

Resolves: https://github.com/ksh93/ksh/issues/145
2021-01-05 23:16:53 +00:00
Martijn Dekker
d1483150ab 'cd': properly ignore $CDPATH if initial component is '.' or '..'
@stephane-chazelas writes:
> Per POSIX[*], cd should skip the $CDPATH processing if the first
> component of the directory given to cd is . or ...
>
> Yet, with ksh93u+m 2021-01-03 at least, while that's OK with ..,
> it's not with . with or without the posix option:
>
> $ CDPATH=/ ./ksh -o posix -c 'cd -P ./etc && pwd'
> /etc
> /etc
>
> It seems to be a regression introduced with ksh93u+ as I can't
> reproduce it with ksh93u or any version prior to that. I can also
> reproduce in u+, v- and the ksh2020 from the Ubuntu 20.04
> package.

src/cmd/ksh93/bltins/cd_pwd.c: b_cd():
- Skip $CDPATH processing not only if the path is absolute, but
  also if the initial path component is '.' or '..' (in the latter
  case the $CDPATH processing was done but appeared to be a no-op).

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

[*] https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/cd.html

Fixes: https://github.com/ksh93/ksh/issues/151
2021-01-05 05:04:24 +00:00
Martijn Dekker
3567220898 New semantic versioning scheme; disable vmalloc in release builds
As of this commit, ksh 93u+m has a standard semantic version number
<https://semver.org/>, beginning with 1.0.0-alpha. This is added to
the version string in a way that should be compatible with scripts
parsing ${.sh.version} or $(ksh --version). This addition does not
replace the release date and does not affect $((.sh.version)).

For non-release builds, the version string will be:
	FORK/VERSION+HASH YYYY-MM-DD
e.g.:	93u+m/1.0.0-alpha+41ef7f76 2021-01-03

For release builds, it will be:
	FORK/VERSION YYYY-MM-DD
e.g.:	93u+m/1.0.0 2021-01-03

It is now automatically decided by bin/package whether to build a
release or development build. When building from a directory that
is not a git repository, or if the current git branch name starts
with a number (e.g. '1.0'), the release build is enabled; otherwise
a development build is the default. This is arranged by adding -D
flags to $CCFLAGS as described below. These flags are prepended to
$CCFLAGS, so they can be overridden by adding your own -D or -U
flags via the environment.

In addition, AST vmalloc is disabled for release builds as of this
commit, forcing the use of the OS's standard malloc(3). In 2021,
this is generally more reliable, faster, and more economical with
memory than AST vmalloc. Several memory leaks and crashing bugs are
avoided, e.g.: <https://github.com/ksh93/ksh/issues/95>.

For development builds, vmalloc stays enabled (along with its known
bugs) because this allows the use of the vmstat builtin, making it
much more efficient to test for memory leaks. For more info, see
the regression test script: src/cmd/ksh93/tests/leaks.sh

bin/package, src/cmd/INIT/package.sh:
- Add flags for build type. In $CCFLAGS, define _AST_ksh_release if
  we're not on any git branch or on a git branch whose name starts
  with a number. Otherwise, define _AST_git_commit as the first 8
  characters of the current git commit hash.

src/lib/libast/features/vmalloc:
- If _AST_ksh_release is defined, disable vmalloc and force use of
  the operating system's malloc. Discussion:
  https://github.com/ksh93/ksh/issues/95

src/cmd/ksh93/include/version.h:
- Define new format for version string, adding a semantic version
  number as well as (for non-release builds) the git commit hash.

src/cmd/ksh93/sh/init.c: e_version[]:
- Add a 'v' to the ${.sh.version} feature string if ksh was
  compiled with vmalloc enabled. This allows scripts, such as
  regression tests, to detect this.

src/cmd/ksh93/data/builtins.c: sh_optksh[]:
- Add a copyright line crediting the contributors to ksh 93u+m.

Resolves: https://github.com/ksh93/ksh/issues/95
2021-01-05 04:52:42 +00:00
Harald van Dijk
41ef7f76cf Invocation: fix infinite loop on 'ksh +s'
When starting ksh +s, it gets stuck in an infinite loop continually
trying to parse its own binary as a shell script and rejecting it:

$ arch/linux.i386-64/bin/ksh +s
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
[...]
$ echo 'echo "this is stdin"' | arch/linux.i386-64/bin/ksh +s
arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error]
(no loop, but still ksh trying to parse itself)

src/cmd/ksh93/sh/init.c: sh_init():
- When forcing on the '-s' option upon finding no command
  arguments, also update sh.offoptions, a.k.a. shp->offoptions.
  This avoids the inconsistent state causing this problem.

  In main.c, there is:

  if(sh_isoption(SH_SFLAG))
      fdin = 0;
  else
      (code to open $0 as a file)

  This was entering the else block because sh_isoption(SH_SFLAG)
  was returning 0, and $0 is set to the ksh binary as it is
  supposed to when no other script is provided. When I looked for
  why sh_isoption was returning 0, I found main.c's

  for(i=0; i<elementsof(shp->offoptions.v); i++)
      shp->options.v[i] &= ~shp->offoptions.v[i];

  Before this loop, shp->offoptions tracks which options were
  explicitly disabled by the user on the command line. The effect
  of this loop is to make "explicitly disabled" take precedence
  over "implicitly enabled". My patch removes the registration of
  the +s option.

Fixes: https://github.com/ksh93/ksh/issues/150
Co-authored-by: Martijn Dekker <martijn@inlv.org>
2021-01-03 23:54:36 +00:00
Martijn Dekker
737438a30f tests/path.sh: fix spurious 'whence -a' test failures
A recent change in Github's Ubuntu test runners exposed a problem
in the way the all_paths test function replicates 'whence -a'
functionality, causing spurious regression test failures.
The problem occurs when e.g. /bin is a symlink to /usr/bin, but
both are in $PATH. The all_paths function treats them as separate
but 'whence -a' detects a duplicate and will not output /usr/bin/*.
I have not succeeded in making all_paths match 'whence -a' exactly.

src/cmd/ksh93/tests/path.sh: function all_paths:
- Using the -ef test expression operator, remove entries from $PATH
  that point to the same directory as another entry in $PATH (e.g.
  when /bin is a symlink to /usr/bin but both are in $PATH).
  Avoiding such dupes works around the problem.
2020-12-20 20:10:02 +00:00
Chase
cda1976e4c Properly clean and ignore flat make binaries and libs
bin/package, src/cmd/INIT/package.sh:
- When running bin/package flat make clean, also clean the flat
  hierarchy binaries.

.gitignore:
- Ignore flat hierarchy binaries.
2020-12-20 01:31:26 +00:00
Martijn Dekker
77111310aa name.c: rm duplicate #define Empty
src/cmd/ksh93/sh/name.c:
- The Empty macro (a constant pointer to the empty string) is already
  defined in include/defs.h, so does not need to be repeated here.
2020-12-04 03:49:23 +00:00
Martijn Dekker
67880e35cf tests/builtins.sh: fix false fail when TZ is GMT (re: eaaa0de7)
GMT and UTC have identical time but are used in different contexts.
When the system time zone is set to GMT (e.g. in the UK at winter
time), the 'printf %T' test could fail as it correctly uses GMT
whereas the test expects UTC.

src/cmd/ksh93/tests/builtins.sh:
- Fix possible false negative in 'printf %T\\n now' test by
  replacing GMT with UTC in both 'date' output and 'printf %T'
  output, instead of only the former.
2020-11-26 14:41:44 +00:00
hyenias
88a6baa1a7
Fix floating point numerics having precision of 0 with assignments (#149)
Issuing typeset floating point numerics having a precision of 0
failed as the precision/size was being overwritten with the string
length of the value, e.g. 'typeset -F0 x=5.67' would result in
'typeset -F 4 x=5.6700' as len('5.67') is 4.

src/cmd/ksh93/include/nval.h:

- Created a symbolic name of NV_FLTSIZEZERO to respresent a float
  having a precision/size of 0. NV_FLTSIZEZERO needs to be a
  negative value.

src/cmd/ksh93/bltins/typeset.c:

- In b_typeset(), added code to set tdata.argnum to NV_FLTSIZEZERO
  for E, F, X options.

- In setall(), adjusted code to allow for tp->argnum to be negative.

src/cmd/ksh93/sh/name.c: nv_newattr():

- Adjusted option value only change code to handle NV_FLTSIZEZERO as
  well as changed to directly setting np->nvsize instead of using
  nv_setsize(np,size) as nv_setsize might contain conflicting and/or
  redundant code.

- Added missing conditional check of '!(newatts&NV_INTEGER)' to
  constrain the size==0 code block to justified strings as
  NV_LJUST, NV_RJUST, or NV_ZFILL are only valid for strings if
  NV_INTEGER is not set. This code block was mistakenly setting
  the precision/size value to the length of the value of an
  assignment for floats whereas it should only be performing
  auto assignment length for justified strings.
2020-11-26 13:50:30 +00:00
hyenias
95fe07d869
Improved 'typeset -xu'/'typeset -xl' fix (re: fdb9781e) (#147)
'typeset -xu' and 'typeset -xl' would export the variable but fail
to change case in the value as the check between old and new
attributes did not provide the necesssary insight for lower or
upper case transcoding due to the lower or upper case attribute
being set within typeset.c prior to calling name.c nv_newattr
function.

Previous rhbz#1188377 patch added a conditional check for size==-1
which in effect caused the nv_newattr export code block return
optimization to never be executed as one cannot set any attributes
using the readonly builtin. By altering the size==-1 check to !trans
the export only optimization can run.

Also, the rhbz#1188377 patch altered new_attr function by setting
the new size to oldsize if run by the readonly builtin. The result
of setting size==oldsize allowed the succeeding if statement to
run more frequently and if size was a non-zero value resulted in
nv_setsize resetting the value to what it already was. Investigation
yielded that size was always 0 coming from the readonly builtin.

src/cmd/ksh93/bltins/typeset.c:
- Remove the setting of tdata.argnum to -1 as it is not needed due to
  existing name.c nv_newattr() logic.

src/cmd/ksh93/sh/name.c: nv_newattr():
- Corrected the export only check optimization by using !trans instead
  of using size==-1.
- Removed previous condition check to set size=oldsize if coming from
  the readonly builtin. nv_newattr already had existing logic to
  prevent changing the size via nv_setsize as size is always 0 when
  coming from readonly builtin.
2020-11-26 13:30:24 +00:00
Martijn Dekker
02e4f2da9e fix possible false negatives in whence -a/-v regress tests
src/cmd/ksh93/tests/builtins.sh:
- Remove redundant extra bincat=$(whence -p cat).
- Move whence -v/-a tests to path.sh.
- Fix 'whence -q' test so errors are counted outside of a subshell.

src/cmd/ksh93/tests/path.sh:
- Add all_paths function that is basically a reimplementation of
  'whence -a -p' in shell. Useful for testing 'whence'.
- Move whence -v/-a tests to here, changing them to use all_paths
  where needed. Also fix the 'whence -a' function autoloading
  regression test to do the same. This fixes the tests for systems
  (such as Slackware) where commands such as 'ls' or 'chmod' have
  more than one path in even the default $PATH.
2020-10-22 22:30:12 +02:00
Martijn Dekker
5ea811413e tests/path.sh: tweak to avoid false failure on ancient Mac OS X 2020-10-07 07:59:22 +02:00
Martijn Dekker
213fb932c0 Remove SH_NOLOG vestiges
The '-o nolog' option (which prevented function definitions from being
recorded in the history file) was removed a long time ago, leaving
only a stub for backwards compatibility to stop 'set' from erroring
out if the option is set. But some other vestiges remained.

src/cmd/ksh93/sh/path.c,
src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- Remove a few pointless 'sh_onstate(SH_NOLOG)' statements. As of
  93u+ or earlier, this is never checked for anywhere.

src/cmd/ksh93/sh.1:
- They forgot to remove the 'nolog' option documentation here.
  Specify that it's obsolete and has no effect.

src/cmd/ksh93/data/builtins.c: sh_set[]:
- Be more concise.
2020-10-07 07:59:14 +02:00
Martijn Dekker
dd9bc22928 Mitigate PWD race condition in non-forking subshells
Virtual/non-forking subshells that change the present working
directory (PWD) with 'cd' suffer from a serious race condition. The
PWD is changed within the same process. This means it may not be
possible to change back to the original PWD when exiting the
subshell, as some other process may destroy the PWD or modify its
permissions in the meantime. ksh did not handle this error
condition at all, so, after exiting a subshell that invoked 'cd',
it could silently end up running the script's following command(s)
in the wrong directory. Which might be 'rm -rf *'. So, ouch.

The proper and obvious fix is never to allow a virtual subshell to
change the PWD, as it can never be guaranteed you can return to a
previous directory. If the PWD is changed in a child process, there
is no need to restore it in the parent process, and this whole
problem is avoided. So subshells really should always fork on
encountering a 'cd' command.

But forking is slow. It is not uncommon for scripts to 'cd' in a
subshell that is run repeatedly in a loop.

There is also the issue of custom builtins that can be added to ksh
via shared libraries. In the standard shell language, 'cd' is the
only command that changes the PWD, so we could just make that
command fork the subshell it is run from. But there's no telling
what a custom builtin might do.

So this commit implements a compromise that will not affect
performance unless there is the pathological condition of a PWD
that has been rendered inaccessible in some way:

1. When entering a virtual subshell, if the parent shell's PWD
proves inaccessible upon saving it, the subshell will now fork into
a separate process, avoiding the unrestorable PWD problem.

2. If some attack renders the parent shell's PWD unrestorable
*after* ksh enters a virtual subshell, ksh will now error out when
exiting it. There is nothing else left to do then. Continuing would
mean running arbitrary commands in the wrong PWD.

src/cmd/ksh93/sh/subshell.c:

- Put all the code/variables only needed for fchdir() behind '#if
  _lib_fchdir'. This makes it clearer what's what.
  (I don't know if there is still any system out there without
  fchdir(3); I haven't found any. The chdir(3) fallback version may
  be removed later as there is no way to make it remotely secure.)

- Fix the attempt to use the O_PATH mode for open(2) as a fallback
  for nonexistent O_SEARCH on Linux. Define _GNU_SOURCE on Linux,
  or <fcntl.h> (which is included indirectly) won't define O_PATH.

- Fix use of O_SEARCH. The code was simply wrong, repeating an
  open(".",O_RDONLY) instead. Since a nonexistent O_SEARCH is now
  redefined as either O_PATH or O_RDONLY, we can simply
  open(".",O_SEARCH) and be done with it.

- Fix fatal error handling. Introduce fatal error condition for
  failure to fchdir(3) back to the parent's PWD; rename 'duped' to
  'fatalerror' and use it for error numbers; save and restore errno
  on fatal error so the message will report the cause. (We must
  call errormsg() near the end of sh_subshell() to avoid crashes.)

- If open(".",O_SEARCH) was not able get a file descriptor to our
  PWD on entry, then call sh_subfork() immediately before running
  the subshell commands. (Forking earlier causes a crash.)

- When restoring the PWD, if fchdir(3) fails, do *not* fall back to
  chdir(3). We already know the PWD is inaccessible, so if chdir(3)
  "succeeds" then, it's very likely to be a substitute injected by
  an attacker.

src/cmd/ksh93/bltins/cd_pwd.c:

- If we don't have fchdir(3), then sh_subshell() must fall back to
  chdir(2) to restore the PWD. That is highly vulnerable, as a
  well-timed rename would allow an attacker to usurp the PWD. We
  can't do anything about that if some custom builtin changes the
  PWD, but we can at least make 'cd' always fork a subshell, which
  slows down ksh but removes the need for the parent shell ever to
  restore the PWD. (There is certainly no popular system where this
  is relevant and there might not be any such current system.)

This commit adds no regression test because a portable regression
test is not really doable. Different kernels, external /bin/pwd
utilities, etc. all have quite different behaviour under the
pathological condition of an inaccessible PWD, so both the
before-fix and the after-fix behaviour differs. See link below.

Resolves: https://github.com/ksh93/ksh/issues/141
Thanks to Stéphane Chazelas for the bug report.
2020-10-07 00:52:11 +02:00
Martijn Dekker
4ae962aba6 Fix ksh93/features/options tests
src/cmd/ksh93/features/options:
- Fix unportable SHELLMAGIC test:
  1. /bin/echo does not work on all systems, but /usr/bin/env is a
     de-facto standard path (even NixOS gave in and has it).
  2. Do not try to execute a temp file in /tmp as it might be
     mounted noexec. Use our own $EXECROOT instead.
- rm unnecessary 'exec 9<&-' (it was never opened globally).
- Remove broken SHOPT_UCB test. It had a syntax error, but the
  result is not used anywhere.
2020-10-06 11:03:58 +02:00
Martijn Dekker
efcc66a3f5 fix typos: descritor -> descriptor 2020-10-05 18:39:49 +02:00
hyenias
6697edba1c
Enforce integer base limits of 2 to 64 (#139)
src/cmd/ksh93/bltins/typeset.c: b_typeset():
- For integer bases change argnum check to default values that
  are < 2 or > 64 to 10 instead of allowing invalid base values
  that ksh cannot process.

src/cmd/ksh93/bltins/typeset.c: setall():
- Remove argnum check for integer base of 1 as base cannot be 1.
- Relocate strlen(name) to inside of conditional check for
  np->nvfun as this code does not need to run all.
- Remove no-op oldname code

src/cmd/ksh93/tests/attributes.sh:
- Add typeset -i base bounds checks to default base 10
2020-10-04 10:18:34 +01:00
Martijn Dekker
cefec34774 regress test tweaks
src/cmd/ksh93/tests/builtins.sh:
- Fix a test so it doesn't fail if 'whence -a' finds multiple paths
  for 'ls'.

src/cmd/ksh93/tests/coprocess.sh
- Update known failure comment with current information.
2020-10-03 00:32:32 +02:00
Martijn Dekker
79d1945813 Streamline some shell state flaggery
src/cmd/ksh93/sh/args.c: sh_argprocsub():
- Save and restore state more efficiently by just saving and
  restoring all the state bits in one go using the
  sh_{get,set}state() macros, which are defined in defs.h as:
    #define	sh_getstate()	(sh.st.states)
    #define	sh_setstate(x)	(sh.st.states = (x))
  (and there is yet more evidence that it doesn't matter whether
  we use a 'shp->' pointer or 'sh.' direct access).

src/cmd/ksh93/sh/main.c: exfile():
- Remove a no-op 'sh_offstate(SH_INTERACTIVE);'. It was in the
  'else' clause of 'if(sh_isstate(SH_INTERACTIVE))' so if we get
  there, it is known that this flag is already off.
- To properly disable job control, we also have to save and restore
  the job.jobcontrol variable.

src/cmd/ksh93/sh/xec.c: sh_exec():
- Remove some no-op flaggery from this highly performance-sensitive
  point in the code. Given the immediately preceding:
	volatile int	was_errexit = sh_isstate(SH_ERREXIT);
	volatile int	was_monitor = sh_isstate(SH_MONITOR);
  the following:
	sh_offstate(SH_ERREXIT);
	if(was_errexit&flags)
		sh_onstate(SH_ERREXIT);
  can be reformulated as:
	if(!(flags & sh_state(SH_ERREXIT)))
		sh_offstate(SH_ERREXIT);
  (IOW, if it was already on, don't turn it off and then on again)
  ...and the following:
	if(was_monitor&flags)
		sh_onstate(SH_MONITOR);
  can be removed; it's a no-op because it wasn't preceded by an
  sh_offstate() and if 'was_monitor' is true, this option is known
  to be on. (I considered they may have forgotten an 'sh_offstate'
  there like in the SH_ERREXIT case, but adding that causes several
  regressions in a shtests run.)

src/cmd/ksh93/include/defs.h:
- Remove comment that is evidently long outdated; there is not (or
  no longer) a Shscoped_t type defined anywhere, nor are these
  struct fields replicated in any other type definition.
- Add comment to clarify what the 'states' int in 'struct
  sh_scoped' is for.
2020-10-02 23:58:21 +02:00
Martijn Dekker
48ba6964ad Turn off SH_INTERACTIVE state flag in subshells
By definition, subshells are never interactive, so they should
disable behaviour associated with interactive shells even if the
main shell is interactive.

Most visibly, running a background job from a subshell like
	( some_command & )
now no longer prints a job ID that you cannot use in the main shell.
This behaviour change matches pdksh/mksh, bash, zsh, dash, et al.

Prior discussion:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
(plus the preceding thread)

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- Before running the command(s) in the subshell using sh_exec(),
  turn off the SH_INTERACTIVE shell state flag. (No need to add
  code to restore it as this function already saves and restores
  the entire shell state.)

src/cmd/ksh93/bltins/misc.c: b_bg():
- If there is no job control when using 'bg', 'fg' or 'disown',
  always print the "no job control" error message and not only if
  the shell is in the interactive state. This is also what
  pdksh/mksh, bash and zsh do.
2020-10-02 08:07:28 +02:00
Martijn Dekker
7424844df5 Remove SH_SUBSHELL option vestiges
Mildly interesting: apparently there was once an idea to implement
shared-state command substitutions as a shell option like 'set -o
subshare'. They were implemented using a new ${ syntax; } instead,
but there is a vestigial SH_SUBSHARE option ID in shell.h plus a
check for it in subshell.c that would cause backtick-style command
substitutions (comsub==1) to share their state. That option isn't
defined in data/options.c so it's impossible for a user to set it.

src/cmd/ksh93/include/shell.h,
src/cmd/ksh93/sh/subshell.c:
- Remove SH_SUBSHELL option vestiges.

src/cmd/ksh93/include/defs.h:
- Correct my comment on 'comsub' flag; I was wrong about what the
  values meant. 2 is for a shared-state comsub. (re: 4ce486a7)
2020-10-01 16:58:03 +02:00
Martijn Dekker
d89ef0fafa Fix $LINENO corruption when autoloading functions
Autoloading a function caused the calling script's $LINENO to be
off by the number of lines in the function definition file. In
addition, while running autoloaded functions, errors/warnings were
reported with wrong line numbers.

src/cmd/ksh93/sh/path.c:
- Save $LINENO (shp->inlineno) before autoloading a function, reset
  it to 1 so that the correct line number offset is remembered for
  the function definition, and restore it after.

src/cmd/ksh93/tests/variables.sh:
- Add regression test for $LINENO, directly and in error messages,
  within and outside a non-autoloaded and an autoloaded function.

Fixes: https://github.com/ksh93/ksh/issues/116
2020-10-01 06:13:00 +02:00
Martijn Dekker
be22f3759e sfio/sfpkrd.c: re-allow compiling on ancient systems (re: 9ba2c2e0) 2020-10-01 04:16:33 +02:00
Martijn Dekker
76d71889e2 don't run posix mode regress tests on ksh without -o posix 2020-09-30 20:18:35 +02:00
Martijn Dekker
c049eec854 Fix pipefail with (errexit or ERR trap) regression
ksh 93u+ introduced a regression in the combination of the
'set -o pipefail' and 'set -e'/'set -o errexit' options:

$ ksh93 -o errexit -o pipefail -c \
	'(exit 3) | true; echo "still here despite $? status"'
still here despite 3 status

The bug is in how the the huge sh_exec() function in xec.c handles
the 'echeck' flag. Near the end of sh_exec(), this flag triggers a
sh_chktrap() call to check whether to trigger any traps, including
the ERR trap -- and that same function also handles the errexit
option, which is basically the same as 'trap "exit" ERR'.

We can learn more easily how sh_exec() works by inserting debug
warnings in all its 'switch(type&COMMSK)' cases, like:

    case TCOM:
	errormsg(SH_DICT,ERROR_warn(0),"[DEBUG] TCOM");

... and same for all the others. With that done, the output
of a very simple dummy pipeline looks as follows:

$ arch/*/bin/ksh -c 'true | true | true'
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TFIL
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TFORK
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TFORK
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TSETIO
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TCOM
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TCOM
arch/darwin.i386-64/bin/ksh: warning: [DEBUG] TCOM

So, it looks like sh_exec() handles this pipeline as follows:

	TFIL
	   |_____TFORK
	   |         |_____TCOM
	   |_____TFORK
	   |         |_____TCOM
	   |_____TSETIO
	             |_____TCOM

Each time a pipeline like command1 | command2 | ... is executed,
sh_exec() is invoked with type TFIL; this then recursively invokes
sh_exec() to handle the individual elements. The last element of
the pipe triggers a sh_exec() run with type TSETIO; since it is run
in the current shell environment, it is effectively treated as a
command with an input redirection. All the previous elements are of
type TFORK instead, because they are executed asynchronously in
separate, forked subshell processes. Finally, the TFORK or TSETIO
code then recursively calls sh_exec() again with type TCOM to
actually execute the commands.

When reading the code, we find that the 'echeck' flag is set as
part of the TSETIO code. This makes sense of why only an error in
the last element of the pipe triggers the errexit/ERR trap action.
So that's the bug: the flag is set in the wrong place.

This can be fixed by setting that flag in the TFIL handling code
instead, as this is what calls everything else and collects all the
exit statuses. So the sh_chktrap() call is now executed after
handling the entire pipeline, at the TFIL recursion level.

This also allows getting rid of the special-casing in the buggy
TSETIO version. The SH_ERREXIT state is restored at the end of each
sh_exec() call, so since we're now doing this at a lower recursion
level, it will already have been restored.

src/cmd/ksh93/sh/xec.c: sh_exec():
- Fix the bug as per the above.

src/cmd/ksh93/tests/options.sh:
- Add tests for errexit and ERR trap combined with pipefail.

src/cmd/ksh93/tests/basic.sh:
- Tweak a couple of tests that reported a trap wasn't triggered
  even if it was actually triggered more than once.

Fixes: https://github.com/ksh93/ksh/issues/121
Thanks to Stéphane Chazelas for the bug report.
2020-09-30 17:49:46 +02:00
Martijn Dekker
fdb9781ebb Fix 'typeset -xu', 'typeset -xl' (rhbz#1188377)
'typeset -xu' and 'typeset -xl' would export the variable but fail
to change case in the value under certain conditions.

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-xufix.patch

This applies the patch essentially without change and adds a
regression test based on the reproducer provided in the RH bug.

Unfortunately there is no description of how the patch works and
it's a little obscure to me. As far as I can figure out, the cause
of the problem was that nv_newattr() erroneously processed a
nonexistent size option-argument such as what can be given to
options like typeset -F, e.g. typeset -F3 for 3 digits after the
dot. A nonexistent size argument is represented by the value of -1.
2020-09-30 03:06:54 +02:00
Martijn Dekker
ba0b1bba2b tests/basic.sh: fix for 'ps' that truncates args (re: cefe087d) 2020-09-29 20:43:35 +02:00
Martijn Dekker
7afb30e15c libast: Work around gcc optimiser bug for strdup() (rhbz#1221766)
Red Hat erratum: https://bugzilla.redhat.com/1221766
"Previously, the gcc utility optimized out a non-NULL test in the
ksh implementation of the strdup() function. This caused an
unexpected termination when ksh was executed in a clean chroot
environment. With this update, ksh compilation parameters have been
updated to prevent optimizing out a non-NULL test, and ksh no
longer crashes in clean chroot environments."

The optimizer bug occurs in that function's single-line body:

  return (s && (t = oldof(0, char, n = strlen(s) + 1, 0))) ? (char*)memcpy(t, s, n) : (char*)0;

So it must be the test for non-NULL 's' that fails. And 's' is
declared in the function definition, as follows:

  extern char*
  strdup(register const char* s)

So that makes me wonder if we can work around the bug by simply
removing the 'const' (and the 'register' while we're at it).
However, I have no easy way to verify that at the moment. The Red
Hat patch instead tells gcc to disable optimization for this
function using a #pragma directive.

I have no idea if that gcc optimiser bug has been fixed in the
meantime, but experience from c258a04f has shown that we cannot
trust that it has been fixed (that other optimizer bug is at least
a decade old and still not fixed). So, in it goes, until someone
shows evidence that we no longer need it.

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-badgcc.patch

src/lib/libast/string/strdup.c:
- Tell GCC to disable all optimisations for strdup().
2020-09-29 19:45:46 +02:00
Martijn Dekker
1477b5fff7 Fix possible out-of-bounds write in xec.c:iousepipe (rhbz#1506344)
Discussion/analysis: https://bugzilla.redhat.com/1506344

iousepipe() might write out of bounds, causing a crash, if
subpipe[2] is set to a value >= sh.gd.lim.open_max.

src/cmd/ksh93/sh/xec.c: iousepipe():
- Validate the FD using sh_iovalidfd() before the write.
2020-09-29 05:21:50 +02:00
Martijn Dekker
90941717da tests/basic.sh: fix test for BSD 'ps' (re: cefe087d) 2020-09-29 05:18:43 +02:00
Martijn Dekker
30aee65113 Fix signal/trap behaviour in ksh functions (rhbz#1454804)
Prior discussion:
https://bugzilla.redhat.com/1454804

On 2017-05-23 13:33:25 UTC, Paulo Andrade wrote:
> In previous ksh versions, when exiting the scope of a ksh
> (not posix) function, it would restore the trap table of
> the "calling context" and if the reason the function exited
> was a signal, it would call sh_fault() passing as argument
> the signal value.
>   Newer ksh checks it, but calls kill(getpid(), signal_number)
> after restoring the trap table, but only calls for SIGINT and
> SIGQUIT.
[...]
>   The old way appears to have been more appropriate, but there
> must be a reason to only pass SIGINT and SIGQUIT as it is an
> explicit patch.

The last paragraph is where I differ. This would not be the first
example of outright breakage that appeared to be added deliberately
and that 93u+m has fixed or removed, see e.g. 8477d2ce ('printf %H'
had code that deleted all multibyte characters), cefe087d, or
781f0a39. Sometimes it seems the developers added a little
experiment and then forgot all about it, so it became a misfeature.

In this instance, the correct pre-2012 ksh behaviour is still
explicitly documented in (k)sh.1: "A trap condition that is not
caught or ignored by the function causes the function to terminate
and the condition to be passed on to the caller". Meaning, if there
is no function-local trap, the signal defaults to the parent scope.
There is no language that limits this to SIGINT and SIGQUIT only.
It also makes no sense at all to do so -- signals such as SIGPIPE,
SIGTERM, or SIGSEGV need to be caught by default and to do
otherwise results in misbehaviour by default.

src/cmd/ksh93/sh/xec.c: sh_funscope():
- When resending a signal after restoring the global traps state,
  remove the spurious check that limits this to SIGINT and SIGQUIT.
- Replace it with a check for nsig!=0, as that means there were
  parent trap states to restore. Otherwise 'kill' may be called
  with an invalid signal argument, causing a crash on macOS.

src/cmd/ksh93/tests/signal.sh:
- Update a test to check that a function-local SIGTERM trap is
  triggered correctly when signalled from another process.
- Complete the tests for 3aee10d7; this bug needed fixing before
  we could test that previous fix in a ksh function scope.
- Add a test for triggering global traps from ksh functions,
  testing multiple POSIX-standard signals.
2020-09-29 03:16:39 +02:00
Martijn Dekker
3aee10d781 Fix off-by-one error, possible crash (re: 6193c6a3)
The ksh-20120801-trapcom.patch patch contains an off-by-one error,
which was also imported into 93u+m. When saving signals:

ceb77b136f/src/cmd/ksh93/sh/subshell.c (L572-L592)
572	if((nsig=shp->st.trapmax)>0 || shp->st.trapcom[0])
573	{
574		++nsig;
575		savsig = malloc(nsig * sizeof(char*));
576		/*
577		 * the data is, usually, modified in code like:
578		 *	tmp = buf[i]; buf[i] = strdup(tmp); free(tmp);
579		 * so shp->st.trapcom needs a "deep copy" to properly save/restore pointers.
580		 */
581		for (isig = 0; isig < nsig; ++isig)
582		{
583			if(shp->st.trapcom[isig] == Empty)
584				savsig[isig] = Empty;
585			else if(shp->st.trapcom[isig])
586				savsig[isig] = strdup(shp->st.trapcom[isig]);
587			else
588				savsig[isig] = NULL;
589		}

On line 574, the number of signals 'nsig' is increased by one. That
increase is permanent, so the 'for' loop on line 581 tries to save
one signal state too many.

The increase was a holdout from the ksh93 code from before the
patch. After the patch, it is not required; it is fine to malloc as
many records as there are trapcom elements to save. So it should
simply be removed. xec.c has the same code to save trap states for
ksh functions, and the same applies.

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- Don't increase nsig.

src/cmd/ksh93/sh/xec.c: sh_funscope():
- Same.

src/cmd/ksh93/tests/signal.sh:
- Add test.
2020-09-28 23:13:38 +02:00
Martijn Dekker
f527706f6c tests/functions.sh: speed up a test 2020-09-28 22:41:48 +02:00
Martijn Dekker
ceb77b136f fix ksh login crash on disk full (rhbz#1212992)
Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20140801-diskfull.patch

Prior discussion:
https://www.mail-archive.com/ast-users@lists.research.att.com/msg01037.html
https://www.mail-archive.com/ast-users@lists.research.att.com/msg01038.html
https://www.mail-archive.com/ast-users@lists.research.att.com/msg01042.html
https://bugzilla.redhat.com/1212992

On Fri, 08 May 2015 14:37:45 -0700, Paulo Andrade wrote:
> I have a user with a ksh crashing problem, and that has
> some "Write error: No space left on device" messages
> in /var/log/messages.
>
> After some debugging, and creating a chroot on a file
> disk image, and a test user, and slowly filling the
> "on file" filesystem, e.g.
>
> dd if=/dev/zero of=/mnt/tmp/zerosN bs=1M count=1024
> dd if=/dev/zero of=/mnt/tmp/zerosN bs=1K count=2
>
> until leaving just around 12K, I managed to reproduce the
> problem, and be able to debug it with valgrind and vgdb;
> debugging on these conditions is tricky, as cannot tell
> valgrind to spawn gdb, because then gdb itself would fail
> to start.
>
> So, after following the code enough, I learned that at places
> it handles SH_JMPEXIT, there was almost non existing
> handling of SH_JMPERREXIT.
>
> ksh would evently cause a crash due to the struct
> subshell allocated on stack, in sh/subshell.c:sh_subshell
> kept set to the global subshell_data, after it siglongjmp
> back the stack due to, not fully handling the out of disk
> space errors. It would print a few messages, everytime
> a pipe was created, e.g.:
>
> /etc/profile: line 28: write to 3 failed [No space left on device]
>
> until eventually crashing due to corrupted memory; e.g. the
> references to stack data from sh_subsell in the global
> subshell_data. One strange thing to me in coredump analysis
> was that subshell_data prev field was pointing to itself when
> it eventually crashed, what later was understood and expected...
>
> The attached patch handles SH_JMPERREXIT in the code
> paths SH_JMPEXIT is handled, and the failed login, on
> full disk, ends in a pause() call:
>
> ---terminal 1---
> $ valgrind -q --leak-check=full --free-fill=0x5a --vgdb=full
> --vgdb-error=0 /bin/ksh -l
> ==17730== (action at startup) vgdb me ...
> ==17730==
> ==17730== TO DEBUG THIS PROCESS USING GDB: start GDB like this
> ==17730==   /path/to/gdb /bin/ksh
> ==17730== and then give GDB the following command
> ==17730==   target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=17730
> ==17730== --pid is optional if only one valgrind process is running
> ==17730==
> ==17730== Syscall param mount(type) points to unaddressable byte(s)
> ==17730==    at 0x563377A: mount (in /usr/lib64/libc-2.17.so)
> ==17730==    by 0x493E58: fs3d_mount (fs3d.c:115)
> ==17730==    by 0x493C8B: fs3d (fs3d.c:57)
> ==17730==    by 0x423E41: sh_init (init.c:1302)
> ==17730==    by 0x405CD3: sh_main (main.c:141)
> ==17730==    by 0x405B84: main (pmain.c:45)
> ==17730==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
> ==17730==
> ==17730== (action on error) vgdb me ...
> ==17730== Continuing ...
> /etc/profile: line 28: write to 3 failed [No space left on device]
> ---8<---
>
> ---terminal 2---
> (gdb) c
> Continuing.
> ^C
> Program received signal SIGTRAP, Trace/breakpoint trap.
> 0x00000000055fa470 in __pause_nocancel () from /lib64/libc.so.6
> (gdb) bt
> #0  0x00000000055fa470 in __pause_nocancel () from /lib64/libc.so.6
> #1  0x000000000041e73d in sh_done (ptr=0x793360 <sh>, sig=255) at
> /home/pcpa/rhel/ksh/ksh-20120801/src/cmd/ksh93/sh/fault.c:665
> #2  0x0000000000407407 in exfile (shp=0x4542, iop=0xff, fno=0) at
> /home/pcpa/rhel/ksh/ksh-20120801/src/cmd/ksh93/sh/main.c:604
> #3  0x0000000000405c43 in sh_source (shp=0x793360 <sh>, iop=0x0,
> file=0x524804 <e_sysprofile> "/etc/profile")
>     at /home/pcpa/rhel/ksh/ksh-20120801/src/cmd/ksh93/sh/main.c:109
> #4  0x00000000004060e4 in sh_main (ac=2, av=0xfff000498, userinit=0x0)
> at /home/pcpa/rhel/ksh/ksh-20120801/src/cmd/ksh93/sh/main.c:202
> #5  0x0000000000405b85 in main (argc=2, argv=0xfff000498) at
> /home/pcpa/rhel/ksh/ksh-20120801/src/cmd/ksh93/sh/pmain.c:45
> (gdb)
> ---8<---
2020-09-28 18:01:39 +02:00
Martijn Dekker
e3d7bf1df2 Fix '( command & )' breakage on interactive (rhbz#1217236)
Prior discussion:
https://bugzilla.redhat.com/1217236
Summary: doing
	( some_simple_command & )
i.e., launching a background job from within a subshell, on a ksh
interactive login shell, caused misbehaviour (command not run).

For me on 93u+m, the misbehaviour was different -- an outright
crash in the job handling code following SIGCHLD, backtracing to:
0   ksh				job_unpost + 49 (jobs.c:1655)
1   ksh				job_reap + 1632 (jobs.c:468)
2   libsystem_platform.dylib	_sigtramp + 29
3   ???				0 + 4355528544
4   ksh				ed_getchar + 102 (edit.c:1048)
5   ksh				ed_emacsread + 659 (emacs.c:280)
[...]

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-nohupfork.patch

Lines 1874-1886 in sh_exec() optimise the highly specific case of
'( simple_command & )' by avoiding a sh_subshell() call that sets
up a virtual subshell before forking:

https://github.com/ksh93/ksh/blob/bd283959/src/cmd/ksh93/sh/xec.c#L1874-L1886
1874	else if(((type=t->par.partre->tre.tretyp)&FAMP) && ((type&COMMSK)==TFORK))
1875	{
1876		pid_t	pid;
1877		sfsync(NIL(Sfio_t*));
1878		while((pid=fork())< 0)
1879			_sh_fork(shp,pid,0,0);
1880		if(pid==0)
1881		{
1882			sh_exec(t->par.partre,flags);
1883			shp->st.trapcom[0]=0;
1884			sh_done(shp,0);
1885		}
1886	}
1887	else
1888		sh_subshell(shp,t->par.partre,flags,0);

The original patch inserts the following before the sh_done call on
line 1884:

			sh_offoption(SH_INTERACTIVE);

sh_done() checks for SH_INTERACTIVE and only runs job handling code
if that option is on.

Also, I had missed the need for an update of shgd->current_pid
here. Since 843b546c replaced lots of getpid() calls by reading
that variable, this could cause ksh to SIGCHLD the wrong process.

But even after adding the shgd->current_pid update to the RH patch,
I was still able to make it crash.

src/cmd/ksh93/sh/xec.c: sh_exec(): case TPAR:
- Disable this optimisation outright for interactive or job
  control-enabled shells. I really don't trust it at all, but there
  have been no problem reports for scripts without job control, so
  keep it until such reports surface.
- Update shgd->current_pid so the child doesn't end up signalling
  the wrong process (re: 843b546c).

___________________________________________________________________
P.S.:

It was noted in the Red Hat discussion that ( ... & ) does a double
fork, i.e., a virtual/non-forked subshell always forks before
forking the background job. This extra fork is done by the
following two lines in under 'case TFORK:' in sh_exec() in xec.c:

https://github.com/ksh93/ksh/blob/bd283959/src/cmd/ksh93/sh/xec.c#L1534-L1535
1534	if((type&(FAMP|TFORK))==(FAMP|TFORK))
1535		sh_subfork();

This is executed if we're in a virtual/non-forked subshell, i.e.
shp->subshell is true (note it is false for forked subshells). So
it forks the virtual subshell (the first fork) before running the
background job (the second fork). A background job is recognised by
'type' having both the FAMP (AMP == ampersand == &) and TFORK bits
set and no others.

So the obvious way to remove the double fork is to comment out
these two lines. Indeed, testing that confirms it gone and ksh
appears to work fine at first glance. Does it really? Nearly!
There are just four regression failures in a 'bin/shtests -p' run:

  options.sh[394]: & job delayed by --pipefail, expected '1212 or 1221', got '1122'
  signal.sh[280]: subshell ignoring signal does not send signal to parent (expected 'SIGUSR1', got 'done')
  signal.sh[289]: subshell catching signal does not send signal to parent (expected 'SIGUSR1', got 'done')
  subshell.sh[467]: sleep& in subshell hanging

So, those two lines cannot be removed now and we have to keep the
double fork. But removing them doesn't appear to break very much,
so it may be possible to add some tests so we only do an extra fork
when really necessary. That is a project for another day.
2020-09-28 17:29:10 +02:00
Martijn Dekker
bd283959be Fix lexing of 'case' in do...done in a $(comsub) (rhbz#1241013)
The following caused a spurious syntax error:

$ x=$(for i in 1; do case $i in word) true;; esac; done)
-ksh: syntax error: `;;' unexpected

Prior discussion:
https://bugzilla.redhat.com/1241013

Original patch, backported from 93v- beta, applied without change:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-parserfix.patch
2020-09-27 21:26:09 +02:00
Martijn Dekker
bb15f7fb19 Fix elusive/intermittent DEBUG trap crash (rhbz#1200534)
For one Red Hat customer, the following reproducer consistently
crashed, tough I was not able to reproduce it and neither was RH.
However, the crash analysis is sound (see below).

    function dlog
    {
      fc -ln -0
    }
    trap dlog DEBUG
    >/tmp/blah

Original patch: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20140801-arraylen.patch

The Red Hat bug thread is closed to the public as it also contains
some correspondence with their customer. But it has an excellent
crash analysis from Thomas Gardner which I'm including here for the
record (the line numbers are for their ksh at the time, not 93u+m).

===begin analysis===
> The creation of an empty file instead of a command that executes
> anything causes the coredump.
[...]
> Here is my analysis on the core that was provided by the customer:
>
> (gdb) bt
> #0  sh_fmtq (string=0x1 <Address 0x1 out of bounds>)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/string.c:340
> #1  0x0000000000457e96 in out_string (cp=<value optimized out>, c=32,
>     quoted=<value optimized out>, iop=<value optimized out>)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:444
> #2  0x000000000045804c in sh_debug (shp=0x76d180, trap=0x7f2f13a821e0 "dlog",
>     name=<value optimized out>, subscript=<value optimized out>,
>     argv=0x76e070, flags=<value optimized out>)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:548
> #3  0x000000000045a867 in sh_exec (t=0x7f2f13aafad0, flags=4)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:1265
> [...need go no further...]
>
> In frame 2, we can see it cycling through your classic
> (char **)argv array like:
>
> 543		while(cp = *argv++)
> 544		{
> 545			if((flags&ARG_EXP) && argv[1]==0)
> 546				out_pattern(iop, cp,' ');
> 547			else
> 548				out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
> 549		}
> 550		if(flags&ARG_ASSIGN)
> 551			sfputc(iop,')');
> 552		else if(iop==stkstd)
>
> (we seg-fault after going down the out_string function in line
> 548 up there). The string pointer that points to = 0x1 up in
> frame #0 (sh_fmtq) traces back to the "cp" variable in line 548
> up there. The "argv" variable being referenced up there just gets
> passed in as the fifth argument to this function.
>
> In frame #3 (sh_exec, line 1265), the line that makes the call
> that takes us to frame 2 is:
>
> 1265                     int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_R     AW);
>
> so "com" (the fifth argument) is what's going wrong as it
> descends down through these calls. Looking at where it comes
> from, well, it's assigned here:
>
> 1241                 if(argn==0)
> 1242                 {
> 1243                     /* fake 'true' built-in */
> 1244                     np = SYSTRUE;
> 1245                     *argv = nv_name(np);
> 1246                     com = argv;
> 1247                 }
>
> because as we can see:
>
> (gdb) f 3
> #3  0x000000000045a867 in sh_exec (t=0x7f2f13aafad0, flags=4)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:1265
> 1265						int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
> (gdb) p argn
> $2 = 0
> (gdb)
>
> argn is == 0 here. The tip-off here is that nv_name clearly
> returns a simple pointer to an array of characters, not an array
> of pointers to arrays of characters as is evidenced by the fact
> that the assignment is "*argv = nv_name(np);" not "argv =
> nv_name(np);". Looking at the function nv_name proves that it
> does indeed return a single pointer to an array of characters,
> not a pointer to an array of pointers to arrays of characters.
> Now, com is defined as a 'char **':
>
> 1002         char        *cp=0, **com=0, *comn;
>
> (as it is expected to be in the calls that follow) also, that
> argv is also defined as the effective equivalent a 'char **':
>
> 1237                 static char *argv[1];
>
> Yup, argv is actually an array of pointers (char ** equivalent),
> but that array is restricted to having exactly one element.
> Recalling the assignment in the previously quoted line:
>
> 1245                     *argv = nv_name(np);
>
> we see that the one and only element in that argv array is
> getting assigned a pointer to an array of characters here.
> Nothing necessarily wrong with that, but remember the loop we
> looked at earlier in frame #2 (sh_debug). It went like:
>
> 543		while(cp = *argv++)
> 544		{
> 545			if((flags&ARG_EXP) && argv[1]==0)
> 546				out_pattern(iop, cp,' ');
> 547			else
> 548				out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
> 549		}
>
> which is clearly expecting argv in this context (com in frame 3,
> which really points to that static local single element array
> that is also pointed to by argv in frame 2) to be an array of
> pointers of indefinite size, each element being a pointer, but
> whose last element will be a null pointer. Well, in frame 3 it is
> clearly an array with only a single element, and that one element
> is NOT pointing to null. Watch this:
>
> (gdb) f 3
> #3  0x000000000045a867 in sh_exec (t=0x7f2f13aafad0, flags=4)
>     at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:1265
> 1265						int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
> (gdb) p com
> $8 = (char **) 0x76e060
> (gdb) p &argv
> $9 = (char *(*)[1]) 0x76e060
> (gdb) p com[0]
> $11 = 0x5009c6 "true"
> (gdb) p com[1]
> $10 = 0x1 <Address 0x1 out of bounds>
> (gdb) p argv[0]
> $12 = 0x5009c6 "true"
> (gdb) p argv[1]
> $13 = 0x1 <Address 0x1 out of bounds>
> (gdb)
>
> So, as expected, com and &argv point to the same place, the first
> element points to the constant string "true", but since the array
> is defined as having only one element, when you refer to a second
> element in that array, you get well, whatever random crap happens
> to be in that memory location. When we try to reproduce this
> problem, apparently we're getting 0 there (or we're not quite
> following this same code path, which is also possible), but the
> customer happens to have a "1" in that memory location.
===end analysis===

src/cmd/ksh93/sh/xec.c: sh_exec():
- When processing TCOM (simple command) with an empty/null command,
  increase the size of the static dummy argv[1] array to argv[2],
  ensuring a terminating NULL element so that 'while(cp = *argv++)'
  loops don't crash. (Note that static objects are automatically
  initialised to zero in C.)

src/cmd/ksh93/tests/io.sh:
- Adapt the reproducer, testing a null-command redirection 1000x.
2020-09-27 13:20:03 +02:00
Martijn Dekker
a5d38b1de7 add missing function crash test (re: 6193c6a3)
Of course I was wrong to say the bug had nothing to do with
functions; traps in ksh functions are local, are handled the same
way as traps that are local to virtual subshells, and had the same
crashing bug. So this adds a test for that as well.
2020-09-27 06:46:52 +02:00
Martijn Dekker
6193c6a3c5 Fix crash while handling subshell trap (rhbz#1117404)
Contrary to the RH bug report, this is yet another bug with
virtual/non-forked subshells and has nothing to do with functions.
If a signal is ignored (empty trap) in the main shell while any
trap (empty or not) is set on the same signal in a subshell, a
crash eventually occurred upon restoring state when leaving the
subshell.

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-trapcom.patch

Prior discussion:
https://bugzilla.redhat.com/1117404

Paulo Andrade wrote there:
> The problem is that the sh_subshell function was saving pointers
> that could change, and when restoring, bad things would happen.
[...]
> The only comment I added:
> /* contents of shp->st.trapcom may change */
> may be a bit misleading, the "bad" save/restore already knows it,
> probably I should have added a better description telling that the
> data is, usually, modified in code like:
>
> tmp = buf[i]; buf[i] = strdup(tmp); free(tmp);
>
> so the shp->st.trapcom needs a "deep copy", as done in the
> patch, to properly save/restore pointers.

src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- sh_subshell(), sh_funscope(): Make *savsig/*savstak into a
  **savsig array. Use strdup(3) to save the data and get known
  pointers that will not change. Free these upon restore.
- Change the comment from the patch as Paulo wished he had done.

src/cmd/ksh93/tests/subshell.sh:
- Test 2500 times. This should trigger the crash most of the time.
2020-09-27 06:17:54 +02:00
Martijn Dekker
045fe6a110 Fix: Closing a FD within a comsub broke output (rhbz#1116072)
Another Red Hat patch. "Prior to this update, the result of a
command substitution was lost if a file descriptor used for the
substitution was previously explicitly closed. With this update,
ksh no longer reuses file descriptors that were closed during the
execution of a command substitution. Now, command substitutions
work as expected in the described situation."

Prior discussion:
https://bugzilla.redhat.com/1116072

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20140929-safefd.patch

src/cmd/ksh93/include/io.h,
src/cmd/ksh93/sh/io.c:
- Add sh_iosafefd() function to get a file descriptor that is not
  in use or otherwise occupied (including marked as closed).

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- Use that function to obtain a safe FD upon restoring state when
  exiting a command substitution. I don't really know the how and
  why -- all that I/O magic is still beyond me and the code is
  uncommented as usual.

src/cmd/ksh93/tests/subshell.sh:
- Add regression test from the reproducer in the bug, reduced to
  the minimum necessary.
2020-09-27 04:46:24 +02:00
Martijn Dekker
18b3f4aa28 combining alarm and IFS caused segfault (rhbz#1176670)
The undocumented alarm builtin executes actions unsafely so that
'read' with an IFS assignment crashed when an alarm was triggered.

This applies an edited version of a Red Hat patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-alarmifs.patch

Prior discussion:
https://bugzilla.redhat.com/1176670

src/cmd/ksh93/bltins/alarm.c:
- Add a TODO note based on dgk's 2014 email cited in the RH bug.
- When executing the trap function, save and restore the IFS table.

src/cmd/ksh93/sh/init.c: get_ifs():
- Remove now-unnecessary SHOPT_MULTIBYTE preprocessor directives as
  8477d2ce lets the compiler optimise out multibyte code if needed.
- Initialise the 0 position of the IFS table to S_EOF. This
  corresponds with the static state tables in data/lexstates.c.

src/cmd/ksh93/tests/builtins.sh:
- Crash test.
2020-09-27 03:03:48 +02:00
Martijn Dekker
f7c3565f4e Fix $PWD breakage on fork; cd; exec (rhbz#1168611)
This applies the following Red Hat patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-cdfork.patch

The associated bug report is public, but nearly all info (such as
a reproducer) has been wiped: https://bugzilla.redhat.com/1168611
However, the errata blurb is mildly informative:

"Previously, ksh sometimes incorrectly initialized a variable
holding the path of the working directory. If a program changed the
working directory between forking and ksh execution, then ksh could
contain an incorrect value in the working directory variable. With
this update, initialization of the working directory variable has
been corrected, and ksh now contains the correct value in the
aforementioned situation."

Also, the patch makes a lot of sense on the face of it. It removes
an optimisation in path_pwd() that checks for the directory defined
by e_crondir[] in data/msg.c, which is:

    const char e_crondir[]		= "/usr/spool/cron/atjobs";

Of /usr/spool not existed on any system for decades as it is common
to mount usr as read-only, so all the writable stuff was moved to
/var. So that would never check out. And if 'flag' is nonzero, the
optimizing 'count++' is executed regardless of whether that
directory exists, ensuring that it never gets the real PWD and
defaults to returning ".".

src/cmd/ksh93/sh/path.c:
- Apply patch as described.
- Mark 'flag' variable as NOT_USED to suppress compiler warning.
  Keep it for backwards compat, as some programs that link with
  libshell might use this function (though it's undocumented).

src/cmd/ksh93/include/path.h,
src/cmd/ksh93/data/msg.c:
- Remove now-unused e_crondir[].
2020-09-26 23:00:05 +02:00
Martijn Dekker
960a1a99cd Avoid importing env vars with invalid names (rhbz#1147645)
This imports a new version of the code to import environment
variable values that was sent to Red Hat from upstream in 2014.
It avoids importing environment variables whose names are not valid
in the shell language, as it would be impossible to change or unset
them. However, they stay in the environment to be passed to child
processes.

Prior discussion: https://bugzilla.redhat.com/1147645
Original patch: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-oldenvinit.patch

src/cmd/ksh93/sh/init.c:

- env_init(): Import new, simplified code to import environment
  variable name/value pairs. Instead of doing the heavy lifting
  itself, this version uses nv_open(), passing the NV_IDENT flag to
  reject and skip invalid names.

- Get rid of gotos and a static var by splitting off the code to
  import attributes into a new env_import_attributes() function.
  This is a better way to avoid importing attributes when
  initialising the shell in POSIX mode (re: 00d43960

- Remove an nv_mapchar() call that was based on some unclear
  flaggery which was also removed by upstream as sent to Red Hat.
  I don't know what that did, if anything; looks like it might have
  had something to do with typeset -u/-l, but those particular
  attributes have never been successfully inherited through the
  environment.
    (Maybe that's another bug, or maybe I just don't care as
    inheriting attributes is a misfeature anyway; we have to put up
    with it because legacy scripts might use it. Maybe someone can
    prove it's an unacceptable security risk to import attributes
    like readonly from an environment variable that is inherently
    vulnerable to manipulation. That would be nice, as a CVE ID
    would give us a solid reason to get rid of this nonsense.)

- Remove an 'else cp += 2;' that was very clearly a no-op; 'cp' is
  immediately overwritten on the next loop iteration and not used
  past the loop.

src/cmd/ksh93/tests/variables.sh:

- Test.
2020-09-26 20:57:39 +02:00
Johnothan King
8a34fc40e6
whence -f: ignore functions (#137)
According to 'whence --man', 'whence -f' should ignore functions:
  -f              Do not check for functions.

Right now this is only accomplished partially. As of commit
a329c22d 'whence -f' avoids any output when encountering a
function (in ksh93u+ 'whence -f' has incorrect output). The
return value is still wrong though:

$ foo() { true; }
$ whence -f foo; echo $?
0

This commit fixes the return value and makes 'type -f' error out
when given a function (like in Bash).

src/cmd/ksh93/bltins/whence.c:
- If -f was passed, set 'cp' to NULL since functions should be
  ignored (as documented).
- Simplify return value by avoiding bitwise logic.

src/cmd/ksh93/tests/builtins.sh:
- Add regression tests for 'whence -f' and 'type -f'.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
2020-09-26 19:26:18 +01:00
Martijn Dekker
7e6bbf85b6 Fix another comsub regression (rhbz#1116508) (re: 970069a6)
Another Red Hat patch of a patch. With the new comsub mechanism,
functions could sometimes return the wrong exit status when invoked
from a command substitution.

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-fununset.patch

I have determined that the extra setexit() in the Red Hat patch,
which copies the current exit status to $?, is not needed, as the
code for running functions already sets $? on termination. I've
added extra regression tests to prove this.

    By the way, the setexit() macro is defined like this in defs.h:

            #define exitset()	(sh.savexit=sh.exitval)

    That's more evidence (see also 3654ee73) that it does not
    matter whether you address the shell's status struct via a
    pointer. That macro is used in places that use shp pointers.
    But, that aside...

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- When waiting within a command substitution for a forked process
  to end, save & restore sh.exitval (the exit status of the command
  currently being run) so that job_wait() cannot override it.

src/cmd/ksh93/tests/functions.sh:
- Add tests based in part on the reproducer from rhbz#1116508.
2020-09-26 02:54:58 +02:00
Martijn Dekker
95225e1e01 tests/subshell.sh: test from rhbz#1138751 reproducer (re: 4ce486a7) 2020-09-26 01:17:19 +02:00
Martijn Dekker
c382cea176 fix non-null pointer check (re: b7932e87)
src/cmd/ksh93/sh/xec.c: sh_funct():
- The np->nvalue.rp pointer was dereferenced before the check that
  it is non-null. Do this check before dereferencing it.
2020-09-25 23:46:24 +02:00
Martijn Dekker
352e68dabd do not resend signal on termination (rhbz#1075635)
public bug: https://bugzilla.redhat.com/1075635
patched by: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-sufix.patch

src/cmd/ksh93/sh/io.c: io_prompt():
- Reset the currently running command's exit status (exitval) when
  writing the prompt. This does not affect "$?" which is savexit.
2020-09-25 23:26:25 +02:00
Martijn Dekker
3050bf28bc whence -v/-a: report path to autoloadable functions
Since at least 1999, whence -v on pdksh (and its successor mksh)
reports the path where an autoloadable function may be found:

  $ mkdir ~/fun; FPATH=~/fun
  $ echo 'myfn() { echo hi; }' >~/fun/myfn
  $ whence -v myfn
  myfn is a undefined (autoload from /home/user/fun/myfn) function

Whereas ksh93 only reports, rather uselessly:

  myfn is an undefined function

As of this commit, whence -v/-a on ksh 93u+m does the same as
pdksh, but with correct grammar:

  myfn is an undefined function (autoload from /home/user/fun/myfn)

This may be a small violation of my own "no new features" policy
for 93u+m, but I couldn't resist. This omission has been annoying
me, and it's just embarrassing to lack a pdksh feature :)

src/cmd/ksh93/include/path.h,
src/cmd/ksh93/data/msg.c:
- Add e_autoloadfrom[] = " (autoload from %s)" message.

src/cmd/ksh93/bltins/whence.c: whence():
- Report the path (if any) when reporting an undefined function.
  This needs to be done in two places:
  1. When a function has been explicitly marked undefined with
     'autoload', we need to do a quick path_search() loop to find
     the path. (These undefined functions take precedence over
     regular commands, so are reported first.)
  2. When a function is not explicitly autoloaded but merely
     available in $FPATH, that path search was already done, so all
     we need to do is report it. (These are reported last.)
  Note that the output remains as on 93u+ if no function definition
  file is found on $FPATH. This is also like pdksh/mksh.

src/cmd/ksh93/data/builtins.c:
- Bump 'whence' version date. The inline docs never detailed very
  exactly what 'whence -v' reports, so no need for further edits.

src/cmd/ksh93/tests/path.sh:
- Regress-test the new whence behaviour plus actual autoloading,
  including the command override behaviour of autoloaded functions.
2020-09-25 17:45:40 +02:00
Martijn Dekker
cefe087d23 Fix argv rewrite on invoking hashbangless script (rhbz#1047506)
The fixargs() function is invoked when ksh needs to run a script
without a #!/hashbang/path. Instead of letting the kernel invoke a
shell, ksh exfile()s the script itself from sh_main(). In the
forked child, it calls fixargs() to set the argument list in the
environment to the args of the new script, so that 'ps' and
/proc/PID/cmdline show the expected output.

But fixargs() is broken because, on systems other than HP-UX (on
which ksh uses pstat(2)), ksh simply inserts a terminating zero.
The arguments list is not a zero-terminated C string. Unix systems
expect the entire arguments buffer to be zeroed out, otherwise 'ps'
and /proc/*/cmdline will have fragments of previous command lines
in the output.

The Red Hat patch for this bug is:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-argvfix.patch

However, that fix is incomplete because 'command_len' was also
hardcoded to be limited to 64 characters (!), which still gave
invalid 'ps' output if the erased command line was longer.

src/cmd/ksh93/sh/main.c: fixargs():

- Remove CMD_LENGTH macro which was defined as 64.

- Remove code that limited the erasure of the arguments buffer to
  CMD_LENGTH characters. That code also had quite a dodgy strdup()
  call -- it copies arguments to the heap, but they are never freed
  (or even used), so it's a memory leak. Also, none of this is
  ever done if the length is calculated using pstat(2) on HP-UX,
  which is a clear indication that it's unnecessary.
  (I think this code block must have been some experiment they
  forgot to remove. One reason why I think so is that a 64 byte
  arguments limit never made sense, even in the 1980s when they
  wrote ksh on 80-column CRT displays. Another indication of this
  is that fixing it didn't require adding anything; the code to do
  the right thing was already there, it was just being overridden.)

- Zero out the full arguments length as in the Red Hat patch.

src/cmd/ksh93/tests/basic.sh:

- Add test. It's sort of involved because 'ps' is one of the least
  portable commands in practice, in spite of standardisation.
2020-09-25 15:02:51 +02:00
Johnothan King
651bbd563e
Fix garbled output from Ctrl+Alt+V (#135)
This fixes a regression introduced in commit f9c127e3.
When the legacy code for older versions of libast was
removed, the fmtident wrapper wasn't removed. As a result,
the version string output by Ctrl+Alt+V is garbled because
the fmtident wrapper doesn't do any formatting:

$ <Ctrl+Alt+V>
^J@(#)$Id: Version AJM 93u+m 2020-09-14

src/cmd/ksh93/sh/string.c:
- Remove the old version of fmtident that was overriding
  the current version of fmtident provided by libast
  (in src/lib/libast/string/fmtident.c).
2020-09-25 03:37:22 +01:00
Martijn Dekker
e40aaa8aa8 Simplify comsub logic (re: 970069a6, 4ce486a7)
There was still an opportunity for code simplification.
No change in behaviour.
2020-09-24 15:43:49 +02:00
Martijn Dekker
a14d17c0f4 Allow turning off brace expansion in comsubs (rhbz#1078698)
There was no check for the -B/braceexpand option before calling
path_expand() to process brace expansion, making it impossible to
turn off brace expansion within command substitutions. Normally the
lexer flags brace expansion so that this code is not reached, but
shell code within command substitutions is handled differently.

Red Hat patches this by adding this check to the function itself:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20140301-fikspand.patch
But I think it's more logical to patch it at the point of decision.

src/cmd/ksh93/sh/macro.c: endfield():
- Decide to call either path_generate() or path_expand() based on
  the state of the SH_BRACEEXPAND shell option.
- Fix '#if SHOPT_BRACEPAT' preprocessor check that previously
  hardcoded this decision at compile time.

src/cmd/ksh93/tests/options.sh:
- Add tests.
2020-09-24 08:21:37 +02:00
Martijn Dekker
c1d9eed54b tests/math.sh: do not break loop; show all errors (re: d7c90ead) 2020-09-24 06:51:11 +02:00
Martijn Dekker
02a48218f3 add another comsub regress test variant (re: 6e515f1d) 2020-09-24 06:31:56 +02:00
Martijn Dekker
4ce486a7a4 Fix hang in comsubs (rhbz#1062296) (re: 970069a6)
The new command substitution mechanism imported in 970069a6 from
Red Hat patches introduced this bug: backtick-style command
substitutions hang when processing about 117KiB of data or more.

It is fixed by another Red Hat patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20140415-hokaido.patch

It saves the value of the shp->comsub flag so that it is set to 2
(usually meaning new-style $(comsubs)) in two specific cases even
when processing backtick comsubs. This stops the sh_subtmpfile()
function in subshell.c from creating a /tmp file. However, I think
that approach is quite ugly, so I'm taking a slightly different one
that has the same effect.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/subshell.c:
- Redefine sh_subtmpfile() to pass the comsub flag as an argument.
  (Remove the shp pointer argument, which is redundant; a pointer
  to the shell state can easily be obtained in the function.)

src/cmd/ksh93/sh/xec.c: sh_exec():
- Apply the Red Hat fix by passing flag 2 to sh_subtmpfile().

src/cmd/ksh93/tests/subshell.sh:
- Move regress test from ce68e1be from basic.sh to here; this is
  the place for command substitution tests as they are subshells.
- Add regress test for this bug.

All other changed files:
- Update sh_subtmpfile() calls to pass on the shp->comsub flag.
2020-09-24 06:07:12 +02:00
Martijn Dekker
3654ee73c0 Fix typeset -l/-u crash on special vars (rhbz#1083713)
When using typeset -l or -u on a variable that cannot be changed
when the shell is in restricted mode, ksh crashed.

This fixed is inspired by this Red Hat fix, which is incomplete:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-tpstl.patch

The crash was caused by the nv_shell() function. It walks though a
discipline function tree to get the pointer to the interpreter
associated with it. Evidently, the problem is that some pointer in
that walk is not set correctly for all special variables.

Thing is, ksh only has one shell language interpreter, and only one
global data structure (called 'sh') to keep its main state[*]. Yet,
the code is full of 'shp' pointers to that structure. Most (not
all) functions pass that pointer around to each other, accessing
that struct indirectly, ostensibly to account for the non-existent
possibility that there might be more than one interpreter state.
The "why" of that is an interesting cause for speculation that I
may get to sometime. For now, it is enough to know that, in the
code as it is, it matters not one iota what pointer to the shell
interpreter state is used; they all point to the same thing (unless
it's broken, as in this bug).

So, rather than fixing nv_shell() and/or associated pointer
assignments, this commit simply removes it, and replaces it with
calls to sh_getinterp(), which always returns a pointer to sh (see
init.c, where that function is defined as literally 'return &sh').

[*] Defined in shell.h, with the _SH_PRIVATE part in defs.h

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/name.c:
- Remove nv_shell().

src/cmd/ksh93/sh/init.c:
- In all the discipline functions for special variables, initialise
  shp using sh_getinterp() instead of nv_shell().

src/cmd/ksh93/tests/variables.sh:
- Add regression test for typeset -l/-u on all special variables.
2020-09-24 03:03:29 +02:00
Martijn Dekker
843b546c1a rm redundant getpid(2) syscalls (re: 9de65210)
Now that we have ${.sh.pid} a.k.a. shgd->current_pid, which is
updated using getpid() whenever forking a new process, there is no
need for anything else to ever call getpid(); we can use the stored
value instead. There were a lot of these syscalls kicking around,
some of them in performance-sensitive places.

The following lists only changes *other* than changing getpid() to
shgd->currentpid.

src/cmd/ksh93/include/defs.h:
- Comments: clarify what shgd->{pid,ppid,current_pid} are for.

src/cmd/ksh93/sh/main.c,
src/cmd/ksh93/sh/init.c:
- On reinit for a new script, update shgd->{pid,ppid,current_pid}
  in the sh_reinit() function itself instead of calling sh_reinit()
  from sh_main() and then updating those immediately after that
  call. It just makes more sense this way. Nothing else ever calls
  sh_reinit() so there are no side effects.

src/cmd/ksh93/sh/xec.c: _sh_fork():
- Update shgd->current_pid in the child early, so that the rest of
  the function can use it instead of calling getpid() again.
- Remove reassignment of SH_PIDNOD->nvalue.lp value pointer to
  shgd->current_pid (which makes ${.sh.pid} work in the shell).
  It's constant and was already set on init.
2020-09-23 04:19:02 +02:00
Martijn Dekker
ce68e1be37 Fix crash in backtick comsubs with job control on (rhbz#825520)
This imports another fix from Red Hat/Fedora. Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-crash.patch

src/cmd/ksh93/include/jobs.h,
src/cmd/ksh93/sh/jobs.c,
src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- Import the Red Hat fix with these differences:
  - Rename the 'hack1_waitall' variable to 'bktick_waitall' and add
    a comment describing what it's for.
  - Remove unused 'pipefail' variable.

src/cmd/ksh93/tests/basic.sh:
- Regression test from reproducer given in the Red Hat bug report.
- Add special handling to SIGKILL it, as it might freeze hard.
2020-09-23 01:56:09 +02:00
Martijn Dekker
f7ffaaba17 tests/builtin.sh: add 'cd' regress tests
These are based on Red Hat patches and/or bug reports.
None of these bugs currently exist in 93u+m, but let's
make sure to keep it that way.
2020-09-22 21:38:15 +02:00
Martijn Dekker
600cb182e3 bin/package: don't test-compile using possibly broken dev shell 2020-09-22 16:14:53 +02:00
Martijn Dekker
7444fc7c24 better v=$(<file) fix (re: fe6d0903)
If we're adding a check for flag==3 to limit the fix to v=$(<file),
we might as well use the existing check upon returning the FD.
2020-09-22 14:39:28 +02:00
Martijn Dekker
e149cf4fd8 tests/builtin.sh: tweaks 2020-09-22 06:52:39 +02:00
Martijn Dekker
03cf032349 fix unportable path in regress test (re: a329c22d) 2020-09-22 03:33:56 +02:00
Martijn Dekker
fe6d0903dc Fix v=$(<file) for closed FD 0,1,2 (rhbz#1066589)
var=$(< file) now reads the file even if the standard inout,
standard output and/or standard error file descriptors are closed.

Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-filecomsubst.patch

src/cmd/ksh93/sh/io.c: sh_redirect():
- When processing the '<' redirector as part of $(< ...), i.e. if
  flag==3, make sure the FD of the file to read is > 2 by calling
  sh_iomovefd(). Unlike the RedHat patch, this checks for flag==3
  to avoid unnecessary sh_iomovefd() calls for normal redirections,
  as there was no bug with those.

src/cmd/ksh93/tests/io.sh:
- Add test.
2020-09-22 03:02:06 +02:00
Martijn Dekker
5683155cb5 update NEWS, SH_RELEASE (re: 970069a6) 2020-09-22 01:45:01 +02:00
Martijn Dekker
970069a6fe Fix command substitutions in here-docs (rhbz#994241, rhbz#1036802)
When ksh was compiled with SHOPT_SPAWN (the default), any command
substitution embedded in a here-document returned an empty string.
The bug was also present in 93u+ 2012-08-01 (although not in every
case as some systems compile it without SHOPT_SPAWN).

This fixes it by applying a slightly edited combination of two Red
Hat patches (the second containing a fix for the first), which
backport a new command substitution mechanism from the abandoned
ksh 93v- beta version. The originals are:

https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-macro.patch
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-fd2lost.patch

src/cmd/ksh93/include/io.h:
- The iopipe() function from xec.c is now needed in sh_subshell()
  (subshell.c), so rename it to sh_iounpipe() and declare it as an
  extern here. The 93v- beta did it as well. (The Red Hat patch did
  this without renaming it.)

src/cmd/ksh93/sh/xec.c:
- Backport new versions of iousepipe() and sh_iounpipe() from ksh
  93v-. New 'type' flaggery is introduced to distinguish between
  different command substitution conditions. What all that means
  remains to be determined.
- sh_exec(): I made one change to the Red Hat patch myself: if in a
  subshell and the type flags FAMP (for "ampersand" as in '&' as in
  background job) and TFORK are set, continue to call sh_subfork()
  to fork the subshell unconditionally, instead of only if we're in
  a command substitution connected to an unseekable file. Maybe the
  latter works for the 93v- code, but on 93u+(m) it causes a couple
  of regressions, which are fixed by my change:
  signal.sh[273]: subshell ignoring signal does not send signal to parent
  signal.sh[276]: subshell catching signal does not send signal to parent
  Details: https://github.com/ksh93/ksh/issues/104#issuecomment-696341902

src/cmd/ksh93/sh/macro.c,
src/cmd/ksh93/sh/subshell.c:
- Updates that go with those new functions.

Fixes:   https://github.com/ksh93/ksh/issues/104
Affects: https://github.com/ksh93/ksh/issues/124
2020-09-21 23:02:08 +02:00
Martijn Dekker
0d3bedd67d tests/leaks.sh: avoid false leak: pre-run test (re: fe20311f) 2020-09-21 02:08:29 +02:00
Martijn Dekker
fe20311fe9 Fix command substitution memory leaks (rhbz#982142)
This fixes two memory leaks in old-style command substitutions
(one when invoking an alias, one when invoking an autoloaded
function), as well as a possible third leak with an unknown
reproducer, by applying this Red Hat patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-mlikfiks.patch

src/cmd/ksh93/sh/macro.c: comsubst():
- For as-yet unknown reasons, the alias leak did not occur when
  adding a space at the end of the command substitution, as in
  a=`some_alias `. This fix is a workaround that simply writes
  an extra space to the stack. TODO: a real fix.

src/cmd/ksh93/sh/path.c: funload():
- Add missing free() before return. This fixes the leak with
  autoloaded functions.

src/cmd/ksh93/sh/lex.c: alias_exceptf():
- This function is called "whenever an end of string is found with
  alias". This adds a check for an SF_FINAL stream status flag when
  deciding whether to call free(). In sfio.h this is commented as:
      #define SF_FINAL 11 /* closing is done except stream free */
  When I revert this change, none of the regression tests fail, so
  I don't know how to trigger this supposed leak. But it makes some
  sense given the sfio.h comment, so I'll keep it.

src/cmd/ksh93/tests/leaks.sh:
- Add the reproducers from rhbz#982142 as regression tests
  (including an extra one for nested command substitutions that was
  already fixed as of 93u+, but testing is good).
     I replaced the external 'expr' and 'ls' commands by uses of
  the 'true' builtin, otherwise the tests take far too long to run
  with 16384 iterations. At least the alias leak was still behaving
  identically after replacing 'ls' by 'true'.
2020-09-21 00:36:36 +02:00
Martijn Dekker
e6611916aa tests/coprocess.sh: temp disable known intermittent fail
Export DEBUG_COPROCESS=y to include it in the tests.
See: https://github.com/ksh93/ksh/issues/132
2020-09-20 20:47:49 +02:00
Martijn Dekker
d9f01e0120 path_search(): still close file if not autoloading (re: a329c22d) 2020-09-20 14:59:34 +02:00
Martijn Dekker
a329c22dba Multiple 'whence' and path search fixes
Hopefully this doesn't introduce new bugs, but it does fix at
least the following:

1. When whence -v/-a found an "undefined" (i.e. autoloadable)
   function in $FPATH, it actually loaded the function as a side
   effect of reporting on its existence (!). Now it only reports.

2. 'whence' will now canonicalise paths properly. Examples:
	$ whence ///usr/lib/../bin//./env
	/usr/bin/env
	$ (cd /; whence -v dev/../usr/bin//./env)
	dev/../usr/bin//./env is /usr/bin/env

3. 'whence' no longer prefixes a spurious double slash when doing
   something like 'cd / && whence bin/echo'. On Cygwin, an initial
   double slash denotes a network server, so this was not just a
   cosmetic problem.

4. 'whence -a' now reports a "tracked alias" (a.k.a. hash table
   entry, i.e. cached $PATH search) even if an actual alias by the
   same name exists. This needed fixing because in fact the hash
   table entry continues to be used when bypassing the alias.
   Aliases and "tracked aliases" are not remotely the same thing;
   confusing nomenclature is not a reason to report wrong results.

5. When using 'hash' or 'alias -t' on a command that is also a
   builtin to force caching a $PATH search for the external
   command, 'whence -a' double-reported the path:
	$ hash printf; whence -a printf
	printf is a shell builtin
	printf is /usr/bin/printf
	printf is a tracked alias for /usr/bin/printf
   This is now fixed so that the second output line is gone.
   Plus, if there were multiple versions of the command on $PATH,
   the tracked alias was reported at the end, which is the wrong
   order. This is also fixed.

src/cmd/ksh93/bltins/whence.c: whence():
- Refactor the do...while loop that handles whence -v/-a for path
  searches in such a way that the code actually makes sense and
  stops looking like higher esotericism. Just doing this fixed #2,
  #4 and #5 above (the latter two before I even noticed them). For
  instance, the path_fullname() call to canonicalise paths was
  already there; it was just never used.
- Remove broken 'notrack' flaggery for deciding whether to report a
  hash table entry a.k.a. "tracked alias"; instead, check the hash
  table (shp->track_tree).

src/cmd/ksh93/sh/path.c:
- path_search(): Re #3: When prefixing the PWD, first check if
  we're in '/' and if so, don't prefix it; otherwise, adding the
  next slash causes an initial double slash. (Since '/' is the only
  valid single-character absolute path, all we need to do is check
  if the second character pwd[1] is non-null.)
- path_search(): Re #1: Stop autoloading when called by 'whence':
  * The 'flag==2' check to avoid autoloading a function was
    broken. The flag value is 2 on the first whence() loop
    iteration, but 3 on subsequent ones. Change to 'flag >= 2'.
  * However, this only fixes it if the function file does not have
    the x permission bit, as executable files are handled by
    path_absolute() which unconditionally autoloads functions!
    So, pass on our flag parameter when callling path_absolute().
- path_absolute(): Re #1: Add flag parameter. Do not autoload
  functions if flag >= 2.

src/cmd/ksh93/include/path.h,
src/cmd/ksh93/bltins/typeset.c,
src/cmd/ksh93/sh/main.c,
src/cmd/ksh93/sh/xec.c:
- Re #1: Update path_absolute() calls, adding a 0 flag parameter.

src/cmd/ksh93/include/name.h:
- Remove now-unused pathcomp member from union Value. It was
  introduced in 99065353 to allow examining the value of a tracked
  alias. This commit uses nv_getval() instead.

src/cmd/ksh93/tests/builtins.sh,
src/cmd/ksh93/tests/path.sh:
- Add and tweak various related tests.

Fixes: https://github.com/ksh93/ksh/issues/84
2020-09-20 07:56:09 +02:00
Martijn Dekker
95fc175993 tests/signal.h: double SIGCHLD test sleep time due to intermittent fail 2020-09-18 22:09:47 +02:00
Martijn Dekker
f45a0f1650 -o posix: inverse-sync braceexpand; properly sync letoctal
{Brace,expansion} is potentially incompatible with POSIX scripts,
because in POSIX those are simple literal strings with no special
meaning. So the POSIX option should really turn that off.

As of b301d417, the 'posix' option was also forcing 'letoctal'
behaviour on, without actually setting that option. I've since
found that to be a botch; 'let' may recognise octals without that
option being set, and that looks like a bug.

So as of this commit, the '-o posix' option actually toggles both
of these options off/on and on/of, respectively. 'set +o posix'
toggles them inversely. However, it is now possible to control both
options (and their associated behaviour) independently in between
'set -o posix' and 'set +o posix'. Much better.

src/cmd/ksh93/sh/main.c: sh_main():
- If SH_POSIX was set on init, turn on SH_LETOCTAL by default
  instead of SH_BRACEEXPAND.

src/cmd/ksh93/sh/args.c: sh_applyopts():
- Turn off SH_BRACEEXPAND and turn on SH_LETOCTAL when SH_POSIX is
  turned on (but not if it was already on).
- Turn on SH_BRACEEXPAND and turn off SH_LETOCTAL when SH_POSIX is
  turned off (but not if it was already off).

src/cmd/ksh93/sh/arith.c: arith():
- Revert to pre-b301d417 and only check SH_LETOCTAL option when
  deciding whether 'let' should skip initial zeros.

src/cmd/ksh93/tests/options.sh:
- Update $- test to allow '-o posix' to switch B = braceexpand.

src/cmd/ksh93/sh.1:
- Update.
- Edit for clarity.
2020-09-18 22:07:44 +02:00
Martijn Dekker
dc80f40d40 tests/sigchild.sh: increase a sleep to prevent very rare intermittent fail 2020-09-18 20:06:34 +02:00
Martijn Dekker
fbdf240acb tests/leaks.sh: allow run without vmalloc/vmstate
This allows running 'bin/shtests leaks' on a ksh without the
vmstate builtin and/or that is not compiled with AST vmalloc.
It falls back to 'ps -o rss= -p $$' to get the memory state.

This is in preparation for the beta and release versions, which
will not use vmalloc due to its defects[*]. Unfortunately,
abandoning vmalloc means abandoning the vmstate builtin which makes
it extremely efficient to test for memory leaks.

Because 'ps' only has a KiB granularity and also shows larger
artefacts/variations than vmalloc on most systems, we need many
more iterations (16384) and also tolerate a higher number of bytes
per iterations (8). So the run takes much longer. To tolerate only
2 bytes per iteration, we would need four times as many iterations,
which would make it take too long to run. Since a single word (e.g.
one pointer) on a 64-bit system is 8 bytes, it still seems very
unlikely for a real memory leak to be that small.

This is coded to make it easy to detect and add iteration and
tolerance parameters for a new method to get the memory state,
if some efficient or precise system-specific way is discovered.

I've also managed to trigger a false leak with shcomp in a UTF-8
locale on CentOS on a ksh with vmalloc/vmstate. So this increases
the tolerance for vmalloc from 2 to 4 bytes/iteration.

[*] Discussion: https://github.com/ksh93/ksh/issues/95
2020-09-18 19:45:43 +02:00
Martijn Dekker
69679be8d7 tests/leaks.sh: test unalias (re: 5d50f825) 2020-09-18 16:51:57 +02:00
Martijn Dekker
7303824789 tests/attributes.sh: add reproducer from rhbz#903750 (already fixed in 93u+) 2020-09-18 13:53:53 +02:00
Martijn Dekker
ba752034c0 Fix crash in .paths file handling
When compiling ksh with '-O0 -g -D_std_malloc' on my Mac, the
paths.sh regress test set crashed. This is the test that crashed:

    print 'FPATH=../fun' > bin/.paths
    cat <<- \EOF > fun/myfun
            function myfun
            {
                    print myfun
            }
    EOF
    x=$(FPATH= PATH=$PWD/bin $SHELL -c  ': $(whence less);myfun') 2> /dev/null
    [[ $x == myfun ]] || err_exit 'function myfun not found'

The crash occurred on the second-to-last line. The backtrace
suggests an invalid use of strcpy() with overlapping memory:

0   libsystem_kernel.dylib  __pthread_kill + 10
1   libsystem_pthread.dylib pthread_kill + 284
2   libsystem_c.dylib       abort + 127
3   libsystem_c.dylib       abort_report_np + 177
4   libsystem_c.dylib       __chk_fail + 48
5   libsystem_c.dylib       __chk_fail_overlap + 16
6   libsystem_c.dylib       __chk_overlap + 34
7   libsystem_c.dylib       __strcpy_chk + 64
8   ksh                     path_chkpaths + 1038 (path.c:1534)
9   ksh                     path_addcomp + 1032 (path.c:1481)
10  ksh                     path_addpath + 395 (path.c:1598)
11  ksh                     put_restricted + 626 (init.c:329)
[...]

src/cmd/ksh93/sh/path.c: path_chkpaths():
- When reading the '.paths' file, use memmove(3) instead of
  strcpy(3) as the former does a non-destructive copy with
  tolerance for overlap.
2020-09-18 12:27:52 +02:00
Johnothan King
7e7f137245
Fix a crash on unsetting preset alias (re: ddaa145b) (#133)
The following set of commands caused ksh to crash:

$ unalias history; unalias r
Memory fault

When ksh is compiled with -D_std_malloc, the crash always
occurs when the 'r' alias is removed with 'unalias r',
although with vmalloc 'unalias history' must be run first
for the crash to occur. With the native malloc, the crash
message is also different:

$ unalias history; unalias r
free(): invalid pointer
Abort

This crash happens because when an alias is unset, _nv_unset
removes the NV_NOFREE flag which results in an invalid use
of free(3) as nv_isattr no longer detects NV_NOFREE afterward.
The history and r aliases shouldn't be freed from memory by
nv_delete because those aliases are given the NV_NOFREE attribute.

src/cmd/ksh93/bltins/typeset.c:
- Save the state of NV_NOFREE for aliases to fix the crash
  caused by 'unalias r'.

src/cmd/ksh93/tests/alias.sh:
- Use unalias on both history and r to check for the crash.
  'unalias -a' can't be used to replicate the crash.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
2020-09-18 11:17:20 +01:00
Martijn Dekker
7e5fd3e98d A few job control (-m, -o monitor) fixes (rhbz#960034)
This patch from Red Hat fixes the following:

1. ksh was ignoring the -m (-o monitor) option when specified on
   the invocation command line.

2. Scripts did not properly terminate their background processes
   on Ctrl+C if the -m option was turned off. Reproducer:
	xterm &
	read junk
   When run as a script without turning on -m, pressing Ctrl+C
   should terminate the xterm, and now does.

3. Scripts no longer attempt to set the terminal foreground process
   group ID, as only interactive shells should be doing that.

This makes some progress on https://github.com/ksh93/ksh/issues/119
but we're a long way from fixing all of that.

src/cmd/ksh93/sh/main.c: exfile():
- On non-interactive shells, do not turn off the monitor option.
  Instead, if it was turned on, turn on the SH_MONITOR state flag.

src/cmd/ksh93/edit/edit.c: ed_getchar():
- On Ctrl+C, issue SIGINT to the current process group using
  killpg(2) instead of going via sh_fault(), which handles a
  signal only for the current shell process.

src/cmd/ksh93/sh/jobs.c: job_reap(), job_reset(),
src/cmd/ksh93/sh/xec.c: sh_exec():
- Only attempt to set the terminal foreground process group ID
  using tcsetpgrp(3) if the shell is interactive.

Original patch: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-kshmfix.patch
This was applied to Red Hat's ksh 93u+ on 8 July 2013.
2020-09-18 04:42:27 +02:00
Martijn Dekker
06e721c313 data/signals.c: fix empty SIGINT/SIGPIPE messages
src/cmd/ksh93/data/signals.c includes two checks for the JOBS
identifier; if it is not defined then the interactive shell's
background job signal messages for SIGINT and SIGPIPE are empty.
The cause was that the "jobs.h" header, which defines that ID, was
not #included in signals.c. This commit adds that #include.
(ksh 93u+, ksh 93v- and ksh2020 all have this bug as well.)

Before:

$ sleep 30 &
[1]	86430
$ kill -s INT "$!"
[1] +                          sleep 30 &
$

After:

$ sleep 30 &
[1]	86445
$ kill -s INT "$!"
[1] + Interrupt                sleep 30 &
$
2020-09-18 03:22:26 +02:00
Martijn Dekker
13c3fb21e9 emacs, vi: Support repeat parameters to VT220 keys (re: f2a3f4e3)
In the vi and emacs line editors, repeat count parameters can now
also be used for the arrow keys and the forward-delete key. E.g.,
in emacs mode, <ESC> 7 <left-arrow> will now move the cursor seven
positions to the left. In vi control mode, this would be entered
as: 7 <left-arrow>.

src/cmd/ksh93/edit/emacs.c:
- ed_emacsread(): Upon getting ^[ (ESC), save current repeat count
  in a new variable; restore and reset it upon the next character.
- escape(): Minor bugfix: when processing a ^[[x sequence where 'x'
  is a character other than '~' (which would be DEL), also reinsert
  the final character into the buffer so scripts can detect them.

src/cmd/ksh93/edit/vi.c:
- cntlmode(): Do not reset the repeat count if the command is '[',
  the character following ESC in VT220 escape sequences.
- mvcursor():
  * Do not use getcount() to get the character following '[', as
    that was parsing repetition parameters in the wrong place.
    There wouldn't be any, so this would reset the repeat count.
  * After that, no more need for the special-casing of ^[[3~ (DEL)
    introduced in f2a3f4e3. Move it to within the 'switch' block.
  * When handling left and right arrows and Home and End keys, do
    not modify cursor directly but ed_ungetchar() the corresponding
    traditional command keys as with the rest. Otherwise a repeat
    count parameter would now wrongly survive those keys.

src/cmd/ksh93/sh.1:
- Document control character notation used for vi mode docs.
- Since vi control mode beeps and aborts on ESC except if a
  subsequent [ is already in the input buffer upon receiving ESC,
  document that VT220 escape sequences only preserve repeat counts
  when entered into the input buffer all at once.
- Don't skip the initial ESC in the documentation of the VT220
  escape sequences. In control mode, skipping the initial ESC still
  works as before, but that is now undocumented, as it's really
  nothing more than an artefact of VT220 escape processing.
- Move the two long paragraphs on '-o viraw' and canonical (i.e.
  line-based) input processing from the vi editor introduction to
  the options section under 'viraw'. It is much too arcane for the
  intro, and besides, ksh 93u+ (and hence also 93u+m) has
  SHOPT_VIRAW enabled by default, so the shell is compiled to force
  this option on at all times, making it even less relevant for
  most users.
2020-09-17 19:14:39 +02:00
Martijn Dekker
c24c3dc0af include/edit.h: cleanup: rm unused Edit_t struct members 2020-09-16 06:38:53 +02:00
Martijn Dekker
461a1aebc1 Fix memory leak in typeset (rhbz#1036470)
A memory leak occurred when typeset was used in a function called
from within a command substitution. This fix was backported from
the 93v- beta by Red Hat on 22 Jan 2014. Source:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik3.patch

src/cmd/ksh93/include/name.h,
src/cmd/ksh93/sh/subshell.c:
- Replace the nv_subsaved() function by the version from ksh 93v-.
  This version frees a table from memory if the NV_TABLE flag is
  passed in the new second parameter, a bitmask for flags (which
  was oddly named 'table'; I've renamed it to 'flags').

src/cmd/ksh93/sh/name.c:
- nv_delete(): When calling nv_subsaved(), pass on the NV_TABLE
  flag if given.
- table_unset(): Call nv_delete() with the NV_TABLE flag.

src/cmd/ksh93/tests/leaks.sh:
- Add test based on the reproducer provided in Red Hat bug 1036470.
2020-09-15 23:52:32 +02:00
Martijn Dekker
05683ec75b Fix several memory leaks related to arrays (rhbz#921455)
I now have access to some of the private bugs on the Red Hat bug
tracker. This one doesn't have a lot of information on the patch,
but it contains a good reproducer, so we can at least verify that
it works.

src/cmd/ksh93/sh/array.c,
src/cmd/ksh93/sh/name.c:
- Apply the patch associated with Red Hat bug #921455. Source:
  https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik.patch
  This was applied to Red Hat's ksh on 04 Jul 2013.

src/cmd/ksh93/tests/leaks.sh:
- Add leak tests for associative and indexed arrays in functions
  based on the reproducer from rhbz#921455.
- Both tests still leak (though much less) when run in a locale
  other than C. For now, temporarily set the locale to C and add
  a TODO note. Perhaps another Red Hat patch is yet to fix this.
2020-09-15 07:47:38 +02:00
Martijn Dekker
16e4824c45 emacs.c: unbreak menu-driven pathname completion (re: e8b3274a)
One of the few AT&T fixes applied in early 2020 was a one-line
change to emacs.c tab handling, with only this info in the commit
message:

|  - fix to emacs.c (I think from dgk)

So, it's unknown what that was meant to accomplish, but I did just
find that it breaks menu-driven pathname completion:

$ ls arch/darwin.i386-64/
1) bin/
2) fun/
3) include/
4) lib/
5) man/
6) src/
$ ls arch/darwin.i386-64/3	_

Typing 3+TAB should have inserted 'include/' but inserted a literal
tab instead. Reverting the vague "fix" fixes this bug.
2020-09-15 05:50:08 +02:00
Martijn Dekker
f2a3f4e36b Handle forward-delete key in emacs and vi editors
On every modern system, the forward-delete key on PC/Mac keyboards
generates the VT220 sequence ESC [ 3 ~. Every other shell with an
editor handles this now, ksh93 seems to be the last not to.

src/cmd/ksh93/edit/emacs.c: escape():
- Handle the ^[[3 as part of normal escape processing, then read an
  extra character to check for the final '~'. If detected, insert
  an ERASECHAR key event.

src/cmd/ksh93/edit/vi.c: mvcursor():
- Replace the ^[[3~ sequence by an 'x' command. We have to
  special-case its processing, because vi mode parses numbers as
  repetition operators. The escape sequence contains a number,
  making it incompatible with normal command handling. This means
  number repetitions don't work with the forward-delete key. If
  that annoys anyone enough to fix it, a patch would be welcome.
  For now, it will do to make the forward-delete key stop
  exhibiting bizarre behaviour (beep + change case + move forward).

src/cmd/ksh93/sh.1
- Copy-edit emacs documentation for VT220-style sequences; map them
  to their actual key, otherwise it's meaningless to the reader.
- Document the new forward-delete key behaviour for emacs mode.
- Leave the forward-delete key for vi mode undocumented for now, as
  repetitions don't work, so it doesn't really match the vi canon.
  (OTOH, it doesn't work in vim, either...)
2020-09-15 03:43:53 +02:00
Martijn Dekker
f0be4d95e8 tests/io.sh: add proc subst FD leak test (re: ab5dedde) 2020-09-14 13:52:01 +02:00
hyenias
d7c90eadc3 sfio: correct floating decimal point scaling of fractions (#131)
_sfcvt(), "convert a floating point value to ASCII", did not adjust
for negative decimal place movement as what happens with leading
zeroes. This caused ksh's 'printf %f' formatter to fail to round
floating point values correctly.

src/lib/libast/sfio/sfcvt.c:
- Removed constraint of <1e-8 for doubles by matching what was done
  for long doubles having <.1.
- Corrected a condition when the next power of 10 occurred and that
  new 1 digit was being overwritten by a 0.

 src/cmd/ksh93/tests/math.sh:
- Validate that typeset -E/F formatting matches that of their
  equivalent printf formatting options as well as checking for
  correct float scaling of the fractional parts.
2020-09-14 13:46:40 +02:00
Martijn Dekker
9f2066f146 Improve fix for parentheses in param expansions (re: 5ed9ffd6)
The fix was incomplete: expansions using '?' (${var?w(ord},
${var:?wo)rd}) still did not tolerate parentheses in the word
as regular characters.

It was also possible to simplify the fix by making use of the
ST_BRACE (sh_lexstate7[]) state table. See data/lexstates.c and
include/lexstates.h.

src/cmd/ksh93/sh/lex.c: sh_lex(): case S_MOD1:
- The previous fix tested for modifier operator characters : - + =
  as part of the S_MOD2 case, though they are defined as S_MOD1 in
  the ST_BRACE state table. It only worked because of the
  fallthrough. And it turns out the S_MOD1 case already had a
  similar fix, though incomplete. The new fix effectively cancelled
  the old one out as any S_MOD1 character eventually led to
  'continue'. So it can be simplified by removing most of that
  code, without causing any change in behaviour. Only the mode
  change to the ST_QUOTE state table followed by 'continue' is
  necessary. This also fixes it for the '?' operator as that is
  also defined as S_MOD1 in the ST_BRACE state table.

src/cmd/ksh93/sh/macro.c:
- When skipping a ${...} expansion using sh_lexskip(), use the
  ST_QUOTE state table if the character c is an S_MOD1 modifier
  operator character. This makes it consistent with the S_MOD1
  handling in sh_lex().

src/cmd/ksh93/tests/variables.sh:
- Update regression tests to include ? and :? operators.
2020-09-13 10:15:26 +02:00
Martijn Dekker
ab5dedded7 Work around process substitution file descriptor leak
File descriptors are not properly closed, causing a leak, when
using a process substitution as an argument to a shell function.
See: https://github.com/ksh93/ksh/issues/67

Process substitution uses /dev/fd/NN pseudofiles if the kernel
provides them. This is tested in src/cmd/ksh93/features/options
which causes SHOPT_DEVFD to be defined if /dev/fd/9 can be used.
If not, ksh uses a fallback mechanism involving a temporary FIFO,
which works on all Unix variants.

As it happens, the leak only occurs when using the /dev/fd
mechanism. So, until a fix is found, we can work around the bug by
disabling it. The FIFO mechanism might be slightly less robust,
but it's an improvement over leaking file descriptors. Plus, there
is room for improving it.

src/cmd/ksh93/include/defs.h:
- Unconditionally redefine SHOPT_DEVFD as 0 for now.

src/cmd/ksh93/sh/args.c: sh_argprocsub():
- pathtemp() does appropriate access checks using access(2), but
  there is an inherent race condition between calling it and
  mkfifo(). Make the FIFO mechanism more robust by handling errors,
  trying again if an error occurs that must have resulted from
  losing that race, e.g. file name conflict or temp dir
  permission/location change.
- Initially create the FIFO without any permissions, then chmod()
  the appropriate user read/write permissions. Since mkfifo()
  honours the umask and chmod() does not, this ensures that process
  substitution continues to work if a shell script sets a umask
  that disallows user read or write. (The /dev/fd/ mechanism does
  not care about the umask, so neither should the fallback.)
2020-09-12 20:22:19 +02:00
Martijn Dekker
10cca4767b libast: update /usr/tmp fallback to /var/tmp
To find the temporary files directory to use, the pathtemp()
function (generate a unique path to a temporary file) first checks
$TMPDIR and $TMPPATH, then falls back to /tmp, then to /usr/tmp as
a last resort. But all systems replaced /usr/tmp by /var/tmp
decades ago to allow mounting /usr as read-only, and a /usr/tmp
compatibility symlink is no longer commonly provided.

src/lib/libast/path/pathtemp.c:
- Change TMP2 definition from "/usr/tmp" to "/var/tmp".

src/lib/libast/features/mmap,
src/lib/libast/features/stdio:
- Change "/usr/tmp" to "/var/tmp" in feature tests.
2020-09-12 19:14:27 +02:00
Martijn Dekker
2ae6e2cf55 tests/builtins.sh: correctly count errors (re: 1bc2c74c) 2020-09-12 03:34:57 +02:00
Martijn Dekker
ddaa145b3d Reinstate 'r' and 'history' as preset aliases for interactive ksh
Following a community discussion, it became clear that 'r' is
particularly problematic as a regular builtin, as the name can and
does conflict with at least one legit external command by that
name. There was a consensus against removing it altogether and
letting users set the alias in their login scripts. However,
aliases are easier to bypass, remove or rename than builtins are.
My compromise is to reinstate 'r' as a preset alias on interactive
shells only, along with 'history', as was done in 17f81ebe before
they were converted to builtins in 03224ae3. So this reintroduces
the notion of predefined aliases to ksh 93u+m, but only for
interactive shells that are not initialised in POSIX mode.

src/cmd/ksh93/Makefile,
src/cmd/ksh93/Mamfile,
src/cmd/ksh93/include/shtable.h,
src/cmd/ksh93/data/aliases.c:
- Restore aliases.c containing shtab_aliases[], a table specifying
  the preset aliases.

src/cmd/ksh93/include/shtable.h,
src/cmd/ksh93/sh/init.c:
- Rename inittree() to sh_inittree() and make it extern, because we
  need to use it in main.c (sh_main()).

src/cmd/ksh93/sh/main.c: sh_main():
- Init preset aliases from shtab_aliases[] only if the shell is
  interactive and not in POSIX mode.

src/cmd/ksh93/bltins/typeset.c,
src/cmd/ksh93/tests/alias.sh:
- unall(): When unsetting an alias, pass on the NV_NOFREE attribute
  to nv_delete() to avoid an erroneous attempt to free a preset
  alias from read-only memory. See: 5d50f825

src/cmd/ksh93/data/builtins.c:
- Remove "history" and "r" entries from shtab_builtins[].
- Revert changes to inline fc/hist docs in sh_opthist[].

src/cmd/ksh93/bltins/hist.c: b_hist():
- Remove handling for 'history' and 'r' as builtins.

src/cmd/ksh93/sh.1:
- Update accordingly.

Resolves: https://github.com/ksh93/ksh/issues/125
2020-09-11 21:35:45 +02:00
Martijn Dekker
777dfa3e59 (k)sh.1: invocation-related edits for clarity and completeness 2020-09-11 20:34:48 +02:00
Martijn Dekker
b9d10c5a9c Fix 'command' expansion bug and POSIX compliance
The 'command' name can now result from an expansion, e.g.:
	c=command; "$c" ls
	set -- command ls; "$@"
both work now. This fixes BUG_CMDEXPAN.

If -o posix is on, 'command' now disables not only the "special"
but also the "declaration" properties of builtin commands that it
invokes. This is because POSIX specifies 'command' as a simple
regular builtin, and any command name following 'command' is just
an argument to the 'command' command, so there is nothing that
allows any further arguments (such as assignment-arguments) to be
treated specially by the parser. So, if and only if -o posix is on:
a. Arguments that start with a variable name followed by '=' are
   always treated as regular words subject to normal shell syntax.
b. Since assignment-arguments are not processed as assignments
   before the command itself, 'command' can now stop the shell from
   exiting (as required by the standard) if a command that it
   invokes (such as 'export') tries to modify a readonly variable.
   This fixes BUG_CMDSPEXIT.

Most of 'command' is integrated in the parser and parse tree
executer, so that is where it needed fixing.

src/cmd/ksh93/sh/parse.c: simple():
- If the posix option is on, do not skip past SYSCOMMAND so that
  any declaration builtin commands that are arguments to 'command'
  are not detected and thus not treated specially at parsetime.

src/cmd/ksh93/sh/xec.c: sh_exec():
- When detecting SYSCOMMAND in order to skip past it, not only
  compare the Namval_t pointer 'np' to SYSCOMMAND, but also handle
  the case where that pointer is NULL, as when the command name
  results from an expansion. In that case, search the function tree
  shp->fun_tree for the name and see if that yields the SYSCOMMAND
  pointer. fun_tree is initialised with a dtview to bltin_tree, so
  searching fun_tree instead allows for overriding 'command' with a
  shell function (which the POSIX standard requires us to allow).

src/cmd/ksh93/sh.1,
src/cmd/ksh93/data/builtins.c:
- Update documentation to match these changes.
- Various related edits and improvements.

src/cmd/ksh93/tests/builtins.sh:
- Check that 'command' works if resulting from an expansion.
- Check that 'command' can be overridden by a shell function.
2020-09-11 10:06:43 +02:00
Martijn Dekker
092b90da81 Fix BUG_LOOPRET2 and related return/exit misbehaviour
The 'exit' and 'return' commands without an argument failed to pass
down the exit status of the last-run command when incorporated in a
block with redirection, &&/|| list, 'case' statement, or 'while',
'until' or 'for' loop.

src/cmd/ksh93/bltins/cflow.c:
- Use $?, which is sh.savexit a.k.a. shp->savexit, as the default
  exit status value if there is no argument, instead of
  shp->oldexit. This fixes the default exit status behaviour to
  match POSIX and other shells.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/include/shell.h:
- Remove now-unused sh.oldexit (a.k.a. shp->oldexit) private struct
  member. It appeared to fulfill the same function as sh.savexit,
  but in a slightly broken way.
- Move the savexit/$? declaration from the _SH_PRIVATE part of the
  struct definition to the public API part. Since $? uses this,
  it's clearly a publicly exposed value already, and this is
  generally the one to use. (If anything, it's exitval that should
  have been private.) This declares savexit right next to exitval,
  rewriting the comments to clarify the difference between them.

src/cmd/ksh93/sh/fault.c,
src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- Remove assignments to shp->oldexit.

src/cmd/ksh93/tests/basic.sh:
- Add thorough regression tests for the default exit status
  behaviour of 'return' and 'exit' in various lexical contexts.
- Verify that 'for' and 'case' without any command, as well as a
  lone redirection, still correctly reset the exit status to 0.

Fixes: #117
2020-09-09 20:02:20 +02:00
Johnothan King
400c107773
Fix compile with -D_std_malloc (re: f9c127e) (#130)
src/cmd/ksh93/include/jobs.h:
- The commit that removed legacy code mistakenly removed the
  definition of vmbusy() required for ksh to compile with
  -D_std_malloc. Ksh assumes vmbusy is always a macro, even
  when _std_malloc is defined. This commit reintroduces the
  _std_malloc definition of vmbusy to fix undefined
  reference errors.
2020-09-08 03:20:18 +01:00
Martijn Dekker
6d0c4ac55f tests/coprocess.sh: fix rare fail (re: 712261c8)
A coprocess cleanup test could fail on rare occasions because I had
lowered the 'sleep 1' between two test coprocesses to 'sleep .1'.
This increases the sleep to prevent future spurious fails.

Fixes: https://github.com/ksh93/ksh/issues/129
2020-09-06 22:40:17 +02:00
Martijn Dekker
e1c41bb2de Fix subshell leak for 3 special variables (re: 417883df, bd3e2a80)
Using a process of elimination I've identified ${.sh.level}
(SH_LEVELNOD) as the cause of the crash. This node apparently
cannot be copied or moved without destabilising the shell. It
contains the current depth of function calls and it cannot be
changed by assignment, so this is not actually a problem.
Meanwhile, this commit re-fixes it for the other three.

src/cmd/ksh93/sh/subshell.c:
- Simplify sh_assignok() by removing special-casing for L_ARGNOD,
  SH_SUBSCRNOD and SH_NAMENOD. 'add' now has 3 modes (0, 1, 2).
- The test for a ${ subshare; } was actually wrong. sp->subshare is
  a saved backup value. We must test shp->subshare. (re: a9de50bf)

src/cmd/ksh93/bltins/typeset.c:
- setall(): Update the mode 3 sh_assignok() call.

src/cmd/ksh93/tests/variables.sh:
- Regress-test subshell leaks for all special variables except
  ${.sh.level}.
2020-09-05 20:47:03 +02:00
Martijn Dekker
417883dfdd Revert "Fix subshell leak for 4 special variables (re: bd3e2a80)"
This reverts commit b3d37b00b0.
While ksh's own regression test suite passed just fine, when
running the modernish[*] regression tests uite, ksh either froze
hard (needing SIGKILL) or threw a spurious syntax error.
Cause unknown, but I'm certainly reverting until I find out.

This reintroduces a subshell leak for four special variables.

[*] https://github.com/modernish/modernish
2020-09-05 16:48:17 +02:00
Martijn Dekker
5ed9ffd6c4 This fixes erroneous syntax errors in parameter expansions such as
${var:-wor)d} or ${var+w(ord}. The parentheses now correctly lose
their normal grammatical meaning within the braces. Fix by Eric
Scrivner (@etscrivner) from July 2018 backported from ksh2020.

This fix complies with POSIX:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

src/cmd/ksh93/sh/lex.c: sh_lex():
- Set the ST_QUOTE state when analysing a modifier with parameter
  expansions using operators ':', '-', '+', '='. This state causes
  subsequent characters (including parentheses) to be considered
  quoted, suppressing their normal grammatical meaning.

src/cmd/ksh93/sh/macro.c: varsub():
- Same for skipping the expansion.

Fixes: https://github.com/ksh93/ksh/issues/126
Prior discussion: https://github.com/att/ast/issues/475
2020-09-05 16:20:22 +02:00
Martijn Dekker
b3d37b00b0 Fix subshell leak for 4 special variables (re: bd3e2a80)
The following special variables leaked out of a subshell:
$_, ${.sh.name}, ${.sh.level}, ${.sh.subscript}.
This was due to a faulty optimisation in sh_assignok().
bd3e2a80 fixed that in part, this fixes the rest.

src/cmd/ksh93/sh/subshell.c:
- Simplify sh_assignok() by removing special-casing for these four
  special variables. The 'add' param reverts to a simple boolean.
- The test for a ${ subshare; } was actually wrong. sp->subshare is
  a saved backup value. We must test shp->subshare. (re: a9de50bf)

src/cmd/ksh93/bltins/typeset.c:
- setall(), unall(): Update sh_assignok() calls.

src/cmd/ksh93/tests/variables.sh:
- Regress-test subshell leaks for all special variables.

Closes: #122
2020-09-05 14:38:44 +02:00
Martijn Dekker
00d439605f -o posix: don't import/export variable attributes thru environment
When exporting variables, ksh exports their attributes (such as
'integer' or 'readonly') in a magic environment variable called
"A__z" (string defined in e_envmarker[] in data/msg.c). Child
shells recognise that variable and restore the attributes.

This little-known feature is risky; the environment cannot
necessarily be trusted and that A__z variable is easy to manipulate
before or between ksh invocations, so you can cause a script's
variables to be of the wrong type, or readonly. Backwards
compatibility requires keeping it, at least for now. But it should
be disabled in the posix mode, as it violates POSIX.

To do this, we have to solve a catch-22 in init.c. We must parse
options to know whether to turn on posix mode; it may be specified
as '-o posix' on the command line. The option parsing loop depends
on an initialised environment[*], while environment initialisation
(i.e., importing attributes) should depend on the posix option.

The catch-22 can be solved because initialising just the values
before option parsing is enough to avoid regressions. Importing the
attributes can be delayed until after option parsing. That involves
basically splitting env_init() into two parts while keeping a local
static state variable between them.

src/cmd/ksh93/sh/init.c:
- env_init():
  * Split the function in two stages based on a new
    'import_attributes' parameter. Import values in the first
    stage; import attributes from A__z in the second (if ever).
    Make the 'next' variable static as it keeps a state needed for
    the attributes import stage.
  * Single point of truth, greppability: don't hardcode "A__z" in
    separate character comparisons, but use e_envmarker[].
  * Fix an indentation error.
- sh_init(): When initialising the environment (env_init), don't
  import the attributes from A__z yet; parse options first, then
  import attributes only if posix option is not set.

src/cmd/ksh93/sh/name.c:
- sh_envgen(): Don't export variable attributes to A__z if the
  posix option is set.

src/cmd/ksh93/tests/attributes.sh:
- Check that variable attributes aren't imported or exported
  if the POSIX option is set.

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

This was the last item on the TODO list for -o posix for now.
Closes: #20

[*] If environment initialisation is delayed until after option
    parsing, bin/shtests shows various regressions, including:
    restricted mode breaks; the locale is not initialised properly
    so that multibyte variable names break; $SHLVL breaks.
2020-09-05 11:41:02 +02:00
Martijn Dekker
20fcf22973 tests/attributes.sh: tweak: loop thru array subscripts (re: a2f13c19) 2020-09-05 10:27:07 +02:00
Martijn Dekker
6affd23601 Remove problematic check for standards env vars (re: 921bbcae)
This commit removes the following standards check on init:

	strcmp(astconf("CONFORMANCE",0,0),"standard")==0

This also checks for the POSIXLY_CORRECT variable; the libast
configuration system uses it to set "CONFORMANCE" to "standard",
*but*, only if that parameter wasn't already initialised from the
_AST_FEATURES environment variable (see 'getconf --man').

Problem is, there is a harmful interaction between POSIXLY_CORRECT
and _AST_FEATURES. If the latter exists, it overrides the former.
Not only that, merely querying CONFORMANCE makes astconf create and
export the _AST_FEATURES variable, propagating the current setting
to child ksh processes, which will then ignore POSIXLY_CORRECT.

We could get around this by simply using getenv("POSIXLY_CORRECT").
But then the results may be inconsistent with the AST config state.

The whole thing may not be the best idea anyway. Honouring
POSIXLY_CORRECT at startup introduces a backwards compatibility
issue. Existing scripts or setups may export POSIXLY_CORRECT=y to
put external GNU utilities in standards mode, while still expecting
traditional ksh behaviour from newly initialised shells.

So it's probably better to just get rid of the check. This is not
bash, after all. If ksh is invoked as sh (the POSIX standard
command name), or with '-o posix' on the command line, you get the
standards mode; that ought to be good enough.

src/cmd/ksh93/sh/init.c: sh_init():
- Remove astconf call as per above.
2020-09-05 09:43:22 +02:00
Martijn Dekker
ca9de42d59 -o posix: minor manpage/usage tweaks (re: 921bbcae) 2020-09-05 06:21:32 +02:00
Martijn Dekker
3ede73aa33 fix "$-" expansion for posix option (re: 921bbcae)
In the SHOPT_BASH code, the -o posix option was given a '\374'
(0xFC, 252) single-letter option character. Reasons unclear. The
'set' builtin doesn't accept it. It can be omitted and the option
still works. And it caused the "$-" expansion (listing active
short-form options) to include that invalid high-bit character if
the -o posix option is active, which is clearly wrong.

src/cmd/ksh93/sh/args.c: optksh[], flagval[]:
- Remove '\374' one-letter option equivalent for SH_POSIX.

src/cmd/ksh93/tests/options.sh:
- Add test verifying that '-o posix' does not affect "$-".
2020-09-04 21:03:28 +02:00
Martijn Dekker
bec6556236 update NEWS, SH_RELEASE (re: 6575903d) 2020-09-04 05:29:52 +02:00
Martijn Dekker
6575903d1d Fix ${!} and ${$} throwing syntax error in here-document
The inclusion of the special parameter expansions ${!} and ${$}
(including the braces) in a here-document caused a syntax error.
Bug reported by @Saikiran-m on Github.

src/cmd/ksh93/data/lexstates.c: sh_lexstate7[]:
- Change the state for ! (33) and $ (36) from S_ERR to 0. State
  table 7 is for skipping over ${...}, so this avoids the S_ERR
  state being invoked in sh_lex() (lex.c) for these characters
  while skipping ${...} in a here-doc.

src/cmd/ksh93/tests/heredoc.sh:
- Test evaluating the braces expansion form for all special
  parameters (@ * # ! $ - ? 0) in a here-document.

Fixes: https://github.com/ksh93/ksh/issues/127
2020-09-04 04:54:35 +02:00
Martijn Dekker
f9c127e39e Remove legacy code for older libast versions
Since ksh 93u+m comes bundled with libast 20111111, there's no need
to support older versions, so this is another cleanup opportunity.

src/cmd/ksh93/include/defs.h:
- Throw an #error if AST_VERSION is undefined or < 20111111.
  (Note that _AST_VERSION is the same as AST_VERSION, but the
  latter is newer and preferred; see src/lib/libast/features/api)

All other changed files:
- Remove legacy code for versions older than the currently used
  versions, which are:
  _AST_VERSION    20111111
  ERROR_VERSION   20100309
  GLOB_VERSION    20060717
  OPT_VERSION     20070319
  SFIO_VERSION    20090915
  VMALLOC_VERSION 20110808
2020-09-04 02:31:39 +02:00
Martijn Dekker
8d7f616e75 Remove abandoned SHOPT_ENV experiment
SHOPT_ENV is an undocumented compile-time option implementing an
experimental method for handling environment variables, which is
implemented in env.h and env.c. There is no mention in the docs or
Makefile, and no mention in the mailing list archives. It adds no
new functionality, but at first glance it's a clean-looking
interface.

However, unfortunately, it's broken. Compiling with -DSHOPT_ENV
added to CCFLAGS causes bin/shtests to show these regressions:

functions.sh[341]: export not restored name=value function call -- expected 'base', got ''
functions.sh[1274]: Environment variable is not passed to a function
substring.sh[236]: export not restored name=value function call
variables.sh[782]: SHLVL should be 3 not 2

In addition, 'export' stops working on unset variables.

In the 93v- beta this code is still present, unchanged, though 93v-
made lots of incompatible changes. By the time ksh2020 noticed it,
it was no longer compiling, so it probably wasn't compiling in the
93v- beta either. Discussion: https://github.com/att/ast/issues/504
So the experiment was already abandoned by D. Korn and his team.

Meanwhile it was leaving sh/name.c with two versions of several
enviornment-related functions, and it's not clear which one is
actually compiled without doing detective work tracing header files
(most of the code was made conditional on _ENV_H, which is defined
in env.h, which is included by defs.h if SHOPT_ENV is defined).
This actively hinders understanding of the codebase. And any
changes to these functions would need to be implemented twice.

src/cmd/ksh93/include/env.h,
src/cmd/ksh93/sh/env.c:
- Removed.

src/cmd/ksh93/DESIGN,
src/cmd/ksh93/Makefile,
src/cmd/ksh93/Mamfile:
- Update accordingly.

All other changed files:
- Remove deactivated code behind SHOPT_ENV and _ENV_H.
2020-09-02 16:09:57 +01:00
Martijn Dekker
bc4dbe0627 shtests: add ${.sh.pid} to PS4/xtrace (re: 9de65210) 2020-09-02 15:51:02 +01:00
Martijn Dekker
5395641036 shtests: cd to each test set's temp dir before running
An oops in tests/io.sh (re: c607c48c) wrote temporary files outside
$tmp and into src/cmd/ksh93/tests. Let's fix this properly so it
doesn't happen again.

src/cmd/ksh93/tests/shtests:
- Start each test set in its own temporary directory by default.

src/cmd/ksh93/tests/*.sh:
- Refuse to run if $tmp != $PWD.
- Related cleanups.
2020-09-02 06:02:40 +01:00
Martijn Dekker
55f0f8ce52 -o posix: disable '[ -t ]' == '[ -t 1 ]' hack
On ksh93, 'test -t' is equivalent to 'test -t 1' (and of course
"[ -t ]" is equivalent to "[ -t 1 ]").

This is purely for compatibility with ancient Bourne shell
breakage. No other shell supports this. ksh93 should probably keep
it for backwards compatibility, but it should definitely be
disabled in POSIX mode as it is a violation of the standard; 'test
-t' is an instance of 'test "$string"', which tests if the string
is empty, so it should test if the string '-t' is empty (quod non).

This also replaces the fix for 'test -t 1' in a command
substitution with a better one that avoids forking (re: cafe33f0).

src/cmd/ksh93/sh/parse.c:
- qscan(): If the posix option is active, disable the parser-based
  hack that converts a simple "[ -t ]" to "[ -t 1 ]".

src/cmd/ksh93/bltins/test.c:
- e3(): If the posix option is active, disable the part of the
  compatibility hack that was used for compound expressions
  that end in '-t', e.g. "[ -t 2 -o -t ]".
- test_unop(): Remove the forking fix for "[ -t 1 ]".

src/cmd/ksh93/edit/edit.c:
- tty_check(): This function is used by "[ -t 1 ]" and in other
  contexts as well, so a fix here is more comprehensive. Forking
  here would cause a segfault, but we don't actually need to. This
  adds a fix that simply returns false if we're in a virtual
  subshell that is also a command substitution. Since command
  substitutions always fork upon redirecting standard output within
  them (making them no longer virtual), it is safe to do this.

src/cmd/ksh93/tests/bracket.sh
- Add comprehensive regression tests for test/[/[[ -t variants in
  command substitutions, in simple and compound expressions, with
  and without redirecting stdout to /dev/tty within the comsub.
- Add tests verifying that -o posix disables the old hack.
- Tweak other tests, including one that globally disabled xtrace.
2020-09-01 20:24:44 +01:00
Martijn Dekker
9077fcc3a4 shtests: refuse to run if no /dev/tty (re: 14632361) 2020-09-01 15:43:54 +01:00
Martijn Dekker
5e21cacf7a init: fix sh detection (re: 921bbcae)
ksh was enabling POSIX mode on init if it was invoked as any name
that merely started with 'sh' (after parsing initial 'r'). This
included shcomp, which was bad news.

src/cmd/ksh93/sh/init.c: sh_type():
- Check that the 'sh' is at the end of the string by checking
  for a final zero byte.
- On Windows (_WINIX, see src/lib/libast/features/common), allow
  for a file name extension (sh.exe) by checking for a dot as well.
2020-09-01 09:08:04 +01:00
Martijn Dekker
c607c48c84 Revert <> redir FD except in posix mode (re: eeee77ed, 60516872)
eeee77ed implemented a POSIX compliance fix that caused a potential
incompatibility with existing ksh scripts; it made the (rarely
used) read/write redirection operator, <>, default to file
descriptor 0 (standard input) as POSIX specified, instead of 1
(standard output) which is traditional ksh93 behaviour. So ksh
scripts needed to change all <> to 1<> to override the new default.

This commit reverts that change, except in the new posix mode.

src/cmd/ksh93/sh/lex.c:
- Make FD for <> default to 0 in POSIX mode, 1 otherwise.

src/cmd/ksh93/tests/io.sh:
- Revert <> regression test changes from 60516872; we no longer
  need 1<> instead of <> in ksh code.
2020-09-01 08:48:18 +01:00
Martijn Dekker
fd977388a2 -o posix: allow invoked programs to inherit FDs > 2
If there are file descriptors > 2 opened with 'exec' or 'redirect',
ksh93 has always closed them when invoking another pogram. This is
contrary to POSIX which states:
    Utilities other than the special built-ins […] shall be invoked
    in a separate environment that consists of the following. The
    initial value of these objects shall be the same as that for
    the parent shell, except as noted below.
    * Open files inherited on invocation of the shell, open files
      controlled by the exec special built-in plus any
      modifications, and additions specified by any redirections to
      the utility
    * […]
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12

src/cmd/ksh93/sh/io.c: sh_redirect():
- When flag==2, do not close FDs > 2 if POSIX mode is active.

src/cmd/ksh93/tests/io.sh:
- Regress-test inheriting FD 7 with and without POSIX mode.

src/cmd/ksh93/sh.1:
- Update.
2020-09-01 08:11:27 +01:00
Martijn Dekker
b301d41731 -o posix: always recognise octals in "let" builtin
Though the "let" builtin is not itself a POSIX standard command, it
processes standard shell arithmetic, so it should recognise octals
by leading zeros as POSIX requires if the 'posix' option is on.
This overrides the setting of the 'letoctal' option.

Note that none of this applies to the ((...)) arithmetic command,
which has always recognised leading-octal zeros and does not listen
to 'letoctal'. So setting the posix mode makes this consistent.

src/cmd/ksh93/sh/arith.c:
- When running the 'let' builtin, test that both SH_LETOCTAL and
  SH_POSIX are off before stripping leading zeros to disable octal
  number recognition.
- Cosmetic: fix spurious newline.

src/cmd/ksh93/sh.1:
- Document the change.

src/cmd/ksh93/tests/shtests:
- Make sure to disable posix mode by default for regression tests.
2020-09-01 07:17:22 +01:00
Martijn Dekker
921bbcaeb7 Remove SHOPT_BASH; keep &> redir operator, '-o posix' option
On 16 June there was a call for volunteers to fix the bash
compatibility mode; it has never successfully compiled in 93u+.
Since no one showed up, it is now removed due to lack of interest.

A couple of things are kept, which are now globally enabled:

1. The &>file redirection shorthand (for >file 2>&1). As a matter
   of fact, ksh93 already supported this natively, but only while
   running rc/profile/login scripts, and it issued a warning. This
   makse it globally available and removes the warning, bringing
   ksh93 in line with mksh, bash and zsh.

2. The '-o posix' standard compliance option. It is now enabled on
   startup if ksh is invoked as 'sh' or if the POSIXLY_CORRECT
   variable exists in the environment. To begin with, it disables
   the aforementioned &> redirection shorthand. Further compliance
   tweaks will be added in subsequent commits. The differences will
   be fairly minimal as ksh93 is mostly compliant already.

In all changed files, code was removed that was compiled (more
precisely, failed to compile/link) if the SHOPT_BASH preprocessor
identifier was defined. Below are other changes worth mentioning:

src/cmd/ksh93/sh/bash.c,
src/cmd/ksh93/data/bash_pre_rc.sh:
- Removed.

src/cmd/ksh93/data/lexstates.c,
src/cmd/ksh93/include/shlex.h,
src/cmd/ksh93/sh/lex.c:
- Globally enable &> redirection operator if SH_POSIX not active.
- Remove warning that was issued when &> was used in rc scripts.

src/cmd/ksh93/data/options.c,
src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/args.c:
- Keep SH_POSIX option (-o posix).
- Replace SH_TYPE_BASH shell type by SH_TYPE_POSIX.

src/cmd/ksh93/sh/init.c:
- sh_type(): Return SH_TYPE_POSIX shell type if ksh was invoked
  as sh (or rsh, restricted sh).
- sh_init(): Enable posix option if the SH_TYPE_POSIX shell type
  was detected, or if the CONFORMANCE ast config variable was set
  to "standard" (which libast sets on init if POSIXLY_CORRECT
  exists in the environment).

src/cmd/ksh93/tests/options.sh,
src/cmd/ksh93/tests/io.sh:
- Replace regression tests for &> and move to io.sh. Since &> is
  now for general use, no longer test in an rc script, and don't
  check that a warning is issued.

Closes: #9
Progresses: #20
2020-09-01 06:19:19 +01:00
Martijn Dekker
84331a96fc 'test --man --': fix a few errors (re: 77beec1e) 2020-09-01 03:10:30 +01:00
Martijn Dekker
77beec1e0d restore 'test --man --' oddness (re: fa6a180f)
Following a community objection to its removal, the inline 'test'
manual page along with its strange method of invocation is
restored. I've taken the opportunity to correct several mistakes,
add some missing info, do some copy-editing, and document the way
to get these docs in the main (k)sh.1 manual.

Discussion:
https://github.com/ksh93/ksh/commit/fa6a180f#commitcomment-41897553
2020-08-31 23:43:22 +01:00
Martijn Dekker
fa6a180fdd test/[: remove effectively inaccessible self-doc
Did you know that you could get a manual page for the 'test'/'['
builtin command using one of these strange command lines?

	test --man --

	[ --man -- ]

Neither did I. It's not documented or mentioned anywhere (and this
syntax violates POSIX). So nobody knows about it, which makes that
documentation useless. (The regular --man option doesn't work
because that would break 'test'.) I only found out how to invoke it
when I understood what the uncommented C code handling this does.

The test/[ command's self-documentation is unmaintained since 2003
and somewhat incomplete. It's also mostly redundant with the
documentation on Conditional Expressions in the main (k)sh.1 manual
page. But unlike the latter, this is resident in RAM, wasting
working memory in every shell process.

src/cmd/ksh93/sh.1:
- Add documentation for 'test'/'[' commands (yes, they were not
  mentioned in the main manual page until now), describing them
  in terms of differences from '[[' and recommending the latter.

src/cmd/ksh93/include/test.h,
src/cmd/ksh93/bltins/test.c,
src/cmd/ksh93/data/testops.c:
- Remove RAM-resident --man doc for test/[ command.
- Remove the bizarre option parsing that allowed invoking it.
2020-08-30 08:08:01 +01:00
Martijn Dekker
cd2cf236c2 test/[: use a shell state bit (re: 7003aba4)
Instead of a global 'sh_in_test_builtin' integer flag, it is nicer
to use the mechanism for shell state bits, which was designed for
this sort of thing.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/defs.c:
- Remove global sh_in_test_builtin integer.
- Define new SH_INTESTCMD state bit.

src/cmd/ksh93/bltins/test.c: _ERROR_exit_b_test(), b_test():
- Use the new state bit.
2020-08-30 05:33:59 +01:00
Martijn Dekker
42301639d6 '#if 0' cleanup
This removes various blocks of uncommented experimental code that
was disabled using '#if 0' or '#if 1 ... #else' directives. It's
hard or impossible to figure out what the thoughts behind them
might have been, and we can really do without those distractions.
2020-08-30 04:51:20 +01:00
Martijn Dekker
f8feed1bd2 SHOPT_MULTIBYTE-related cleanup (re: 8477d2ce)
As of 8477d2ce, the mbwide() macro (which tests if we're in a
multibyte locale, i.e. UTF-8) is redefined as a constant 0 if we're
compiling without SHOPT_MULTIBYTE. See src/cmd/ksh93/include/defs.h

The other multibyte macros use mbwide() as well, so they all revert
to the single-byte fallbacks in that case, and the multibyte code
in them is never compiled. See src/lib/libast/include/ast.h

Consequently we can now do a bit of cleanup and get rid of many of
the '#if SHOPT_MULTIBYTE' directives, as the compiler optimiser
will happily remove the multibyte-specific code. This increases the
legibility of the ksh code.

I'm taking the opportunity to fix a few typos and whitespace
formatting glitches as well.
2020-08-30 04:50:57 +01:00
Martijn Dekker
7c5d39fa04 Refactor "$*" multibyte handling (re: 8b5f11dc)
The first of the two multibyte fixes from 8b5f11dc (which was for
using the first character of IFS as an output field separator when
expanding "$*" and similar) had a minor backwards compatibility
problem: if $IFS started with a byte sequence that is not a valid
UTF-8 character, then it treated IFS as empty in UTF-8 locales, so
the fields would be joined without any separator. The expected
behaviour would be for it to fall back to using the first byte of
IFS as it used to (and as bash and zsh do).

The new code handling this was also a bit kludgy and inefficient,
repeating the mbsize() calculation for every byte of the separator
character and for every field joined by the expansion.

src/cmd/ksh93/sh/macro.c: varsub():
- Rewrite code for joining fields for $* in a quoted or scalar
  context and $@ in a scalar context, eliminating a confusing 'd'
  variable and concentrating the routine in one block.
- When expanding $* with a multibyte separator (first character
  of $IFS), only calculate the size in bytes once per expansion.
- If $IFS starts with a byte sequence that represents an invalid
  multibyte character, fall back to using the first byte.

src/cmd/ksh93/tests/variables.sh:
- Tweak some regression tests, including one that overwrote $LANG.
- Add test for invalid multibyte character behaviour as per above.
2020-08-29 21:52:29 +01:00
Johnothan King
8f813bb0a3
Fix a file descriptor leak when fstat errors out with EIO (#120)
src/cmd/ksh93/sh/path.c: canexecute():
- Close file descriptors inside of the err label. This fixes
  a file descriptor leak that occurs when open succeeds but
  fstat fails with EIO. The previous code only returned -1
  after 'goto err', leaving the opened file descriptor
  inaccessible. This bugfix was backported from ksh2020:
  https://github.com/att/ast/commit/55cad1d
2020-08-26 22:19:51 +01:00
Martijn Dekker
e08ca80d15 bin/package: do not use previously compiled shell
The package script searches for a good shell to run the build
scripts, preferring a ksh. But it also finds any recently compiled
development version of ksh in arch/*/bin that may be broken, or
have debug code, etc. -- and uses that in preference to anything
else. This is quite capable of breaking the build process.

The way to get around it is to do something like
	bin/package make SHELL=/bin/ksh
which is annoying to have to keep doing.

bin/package,
src/cmd/INIT/package.sh:
- When finding a good shell, use the saved user path ($path), not
  the current $PATH which includes arch/$HOSTTYPE/bin. Prefix this
  temporary path with `getconf PATH`, the system's default path,
  so that known-good system shells are found first.
2020-08-26 22:15:50 +01:00
Martijn Dekker
9b45f2ccbe build system: modernise shell compatibility checks
All changed files:
- Put the shell in POSIX mode if it has an '-o posix' option.
- Remove nonsense disabling 'set -x' on bash. It's not broken.

bin/package, src/cmd/INIT/package.sh:
- Add check blocking native zsh mode (e.g., "$path" conflicts).
  Using a 'sh -> zsh' symlink works, so recommend that.
- Remove old ksh93 version check for a supposed conflict with
  libcmd. It was broken; it would revert to /bin/sh, but on illumos
  distributions, /bin/sh is a ksh93 of a version that is supposedly
  affected. It builds fine anyway.
- Rewrite checksh() to incorporate the shell compatibility checks
  that were previously in two different places in 'package'.

bin/ignore, src/cmd/INIT/ignore.sh,
bin/silent, src/cmd/INIT/silent.sh:
- Change bad check for a full POSIX 'export' command (no, $RANDOM
  has nothing to do with that) with a proper feature test.
2020-08-23 23:41:31 +01:00
Martijn Dekker
42d1651108 iffe: fix broken shell detection; allow building on NetBSD 9.0
The shell detection test assumed that any shell that has $RANDOM
and isn't bash must be ksh and have the 'print' built-in command.
This broke iffe on NetBSD 9.0 sh, which has $RANDOM but not 'print'.

src/cmd/INIT/iffe.sh:
- Rewrite shell detection test to test for features actually used
  by iffe. "$shell" can now have the values 'bsh' for an ancient
  pre-POSIX Bourne shell, 'bash' for bash, 'ksh' for a shell with
  'let', 'typeset -u' and 'print' (ksh88, ksh93, mksh, pdksh, zsh),
  and 'posix' for another POSIX or POSIX-ish shell with modern
  command substitutions and parameter substitutions. (The 'posix'
  value currently is not actively checked for anywhere, but avoids
  unnecessary use of bsh fallbacks.)
2020-08-23 19:29:20 +01:00
Martijn Dekker
506bd2b23a fix SHOPT_REGRESS crash
If ksh was compiled with -DSHOPT_REGRESS=1, it would immediately
segfault on init. After fixing that, another segfault remained that
occurred when using the --regress= command line option with an
invalid option-argument.

The __regress__ builtin allows tracing a few things (see
'__regress__ --man' after compiling with -DSHOPT_REGRESS=1, or
usage[] in src/cmd/ksh93/bltins/regress.c). It seems of limited
use, but at least it can be used/tested now.

src/cmd/ksh93/sh/init.c: sh_init():
- Move the call to sh_regress_init() up. The crash on init was
  caused by geteuid() being intercepted by regress.c before the
  shp->regress (== sh.regress) pointer was initialised.
- The builtin can also be called using a --regress= option-argument
  on the ksh command line. Before calling b___regress__() to parse
  that, temporarily change error_info.exit so any usage error calls
  exit(3) instead of sh_exit(), as the latter assumes a fully
  defined shell state and this call is done before the shell is
  fully initialised.
2020-08-22 16:03:01 +01:00
Martijn Dekker
f89fc2c713 tests/leaks.sh: add test for PATH reset leak triggered by nmake build 2020-08-21 19:56:39 +01:00
Martijn Dekker
52dc071a56 bin/package: fix a POSIX-ism (re: 3552a2ba)
The INIT scripts are supposed to be Bourne shell scripts, not
POSIX, so we can't use $( ... ) command substitutions.

bin/package,
src/cmd/INIT/package.sh:
- Change a POSIX command substitution to old-style backticks.
2020-08-20 22:49:46 +01:00
Martijn Dekker
9ba2c2e0df Speed up 'read', fixing macOS hang (take 2)
This fixes a hanging bug that could occur on macOS when using the
'read' command to read from a FIFO and encountering end-of-file
without a final newline character. It also makes the 'read' command
perform 15-25% faster on macOS and Linux.

The previous version (ff385e5a) failed on SunOS/Solaris/Illumos
because those systems apparently don't (fully) support the POSIX
standard recv(2) syscall with MSG_PEEK[*], which is the feature
that iffe detects under the 'socket_peek' identifier. On Illumos,
using that methods causes a compilation failure (unknown identifier
MSG_PEEK); on Solaris 11.4, that method causes multiple regressions
in tests/io.sh, suggesting the method compiles but doesn't work at
all. Instead, SunOS/Solaris/Illumos requires the method using
ioctl(2)+I_PEEK and select(2). No other system that ksh currently
builds on requires this method, so it is now only used on
SunOS/Solaris/Illumos.

So far, this version of sfpkrd() has been tested to work correctly
on Linux, macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, and
OmniOS (an Illumos distribution).

It still fails to peek on Cygwin, but in the exact same way it
failed before, so that's no loss.

To test, run the 'io' test set:  bin/shtests -p io

src/lib/libast/sfio/sfpkrd.c: sfpkrd():
- Remove long-obsolete Mac OS X and Solaris bug workarounds.
- Remove methods that are no longer needed.
     On systems with a POSIX compliant recv(2), the only thing that
  is required to avoid regressions is the code that was conditional
  upon the socket_peek feature test, which tests for the correct
  functioning of the recv(2) syscall. This has now been made
  mandatory for non-SunOS/Solaris/Illumos systems (using an #error
  directive if it is not detected), with the other methods removed.
  The result performs 15-25% faster on macOS and Linux while
  passing all the regression tests.
     On macOS, avoiding the select(2) method fixes the hanging bug.
     On SunOS/Solaris/Illumos (the '__sun' identifier), the method
  using ioctl(2)+I_PEEK and select(2) (iffe feature IDs:
  stream_peek and lib_select) is preserved.

Resolves: https://github.com/ksh93/ksh/issues/118 (again)

[*] https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
2020-08-19 23:54:55 +01:00
Martijn Dekker
569c1bb9c1 Revert "Speed up 'read', fixing macOS hang"
This reverts commit ff385e5a89.
It broke Solaris and illumos. More testing is needed.
2020-08-19 04:10:55 +01:00
Martijn Dekker
ff385e5a89 Speed up 'read', fixing macOS hang
This fixes a hanging bug that could occur on macOS when using the
'read' command to read from a FIFO and encountering end-of-file
without a final newline character. It also makes the 'read' command
perform 15-25% faster on macOS and Linux and maybe other systems.

src/lib/libast/sfio/sfpkrd.c: sfpkrd():
- Get rid of the optional stuff that uses the poll(2) or select(2)
  syscalls. The only thing that is required to avoid regressions is
  the code that was conditional upon the socket_peek feature test,
  which tests for the correct functioning of the recv(2) syscall.
  This has now been made mandatory. The rest now uses what was
  previously a fallback in plain C, resulting in a function that is
  not only more readable, but actually faster than the syscalls.

Resolves: https://github.com/ksh93/ksh/issues/118
2020-08-19 01:36:01 +01:00
Chase
c3388ffd85 nval.h: remove dtksh additions & old compat redefs (re: e2d1b593)
CDE <https://cdesktopenv.sf.net/> developer Chase writes, re dtksh:
| Everything is now completely working, and we are almost ready to
| add ksh93 as a submodule, but I have one last commit to get rid
| of some warnings we are facing. nval.h has some of these
| "compatiblity redefines" that are causing issues whenever we
| include it (warnings about redefining values) [...].

src/cmd/ksh93/include/nval.h:
- Replace ancient compatibility redefines by an unconditional
  '#include <hash.h>'; ksh works fine with the "new" hash library.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
2020-08-17 23:11:51 +01:00
Martijn Dekker
d03e948bcd Fix 'command -p' lookup if hash table entry exists (re: c9ccee86)
If a command's path was previously added to the hash table as a
'tracked alias', then the hash table entry was used, bypassing
the default utility path search activated by 'command -p'.

'command -p' activates a SH_DEFPATH shell state. The bug was caused
by a failure to check for this state before using the hash table.
This check needs to be added in four places.

src/cmd/ksh93/sh/path.c,
src/cmd/ksh93/sh/xec.c:
- path_search(), path_spawn(), sh_exec(), sh_ntfork(): Only consult
  the hash table, which is shp->track_tree, if the SH_DEFPATH shell
  state is not active.

src/cmd/ksh93/tests/path.sh:
- Add regress tests checking that 'command -p' and 'command -p -v'
  still search in the default path if a hash table entry exists for
  the command searched.
2020-08-17 20:23:39 +01:00
Martijn Dekker
acf84e9633 Fix 'command -x' on macOS, Linux, Solaris
'command -x' (basically builtin xargs for 'command') worked for
long argument lists on *BSD and HP-UX, but not on macOS and Linux,
where it reliably entered into an infinite loop.

The problem was that it assumed that every byte of the environment
space can be used for arguments, without accounting for alignment
that some OSs do. MacOS seems to be the most wasteful one: it
aligns on 16-byte boundaries and requires some extra bytes per
argument as well.

src/cmd/ksh93/sh/path.c:
- path_xargs(): When calculating how much space to subtract per
  argument, add 16 extra bytes to the length of each argument, then
  align the result on 16-byte boundaries. The extra 16 bytes is
  more than even macOS needs, but hopefully it is future-proof.
- path_spawn(): If path_xargs() does fail, do not enter a retry
  loop (which always becomes an infinite loop if the argument list
  exceeds OS limitations), but abort with an error message.
2020-08-16 09:31:43 +01:00
Martijn Dekker
35ad5e65af sh/name.c: rm ancient binary compat overrides
Four libast hash functions/macros (which ksh93 doesn't actually use)
were overridden with the following comment:
/*
 * These following are for binary compatibility with the old hash library
 * They will be removed someday
 */
This has been there for decades, and I just received word that they
cause problems for the dtksh (CDE) developers as dtksh does call
hashlook().

src/cmd/ksh93/sh/name.c:
- Remove 'hashscope', 'hashfree', 'hashname' and 'hashlook'
  compatibility overrides.
2020-08-16 04:49:18 +01:00
Martijn Dekker
e875616618 shell.3: fix glitch; add missing SH_PRIVILEGED doc 2020-08-15 21:37:46 +01:00
Martijn Dekker
85eb2f735b tests/leaks.sh: rm minor editing glitch 2020-08-14 17:20:26 +01:00
Martijn Dekker
56805b25af Fix leak and crash upon defining functions in subshells
A memory leak occurred upon leaving a virtual subshell if a
function was defined within it. If this was done more than 32766
(= 2^15-2 = the 'short' max value - 1) times, the shell crashed.
Discussion and reproducer: https://github.com/ksh93/ksh/issues/114

src/cmd/ksh93/sh/subshell.c: table_unset():
- A subshell-defined function was never freed because a broken
  check for autoloaded functions (which must not be freed[*]). It
  looked for an initial '/' in the canonical path of the script
  file that defined the function, but that path is also stored for
  regular functions. Now use a check that executes nv_search() in
  fpathdict, the same method used in _nv_unset() in name.c for a
  regular function unset.

src/cmd/ksh93/bltins/misc.c: b_dot_cmd():
- Fix an additional memory leak introduced in bd88cc7f, that caused
  POSIX functions (which are run with b_dot_cmd() like dot scripts)
  to leak extra. This fix avoids both the crash fixed there and the
  memory leak by introducing a 'tofree' variable remembering the
  filename to free. Thanks to Johnothan King for the patch.

src/lib/libast/include/stk.h,
src/lib/libast/misc/stk.c,
src/lib/libast/man/stk.3,
src/lib/libast/man/stak.3:
- Make the stack more resilient by extending the stack reference
  counter 'stkref' from (signed) short to unsigned int. On modern
  systems with 32-bit ints, this extends the maximum number of
  elements on a stack from 2^15-1==32767 to 2^32-1==4294967295.
  The ref counter can never be negative, so there is no reason for
  signedness. sizeof(int) is defined as the size of a single CPU
  word, so this should not affect performance at all.
     On a 16-bit system (not that ksh still compiles there), this
  doubles the max number of entries to 2^16-1=65535.

src/cmd/ksh93/tests/leaks.sh:
- Add leak regression tests for ksh functions, POSIX functions, dot
  scripts run with '.', and dot scripts run with 'source'.

src/cmd/ksh93/tests/path.sh:
- Add an output builtin with a redirect to an autoloaded function
  so that a crash[*] is triggered if the check for an autoloaded
  function is ever removed from table_unset(), as was done in ksh
  93v- (which crashed).

[*] Freeing autoloaded functions after leaving a virtual subshell
    causes a crashing bug: https://github.com/att/ast/issues/803

Co-authored-by: Johnothan King <johnothanking@protonmail.com>
Fixes: https://github.com/ksh93/ksh/issues/114
2020-08-14 00:25:31 +01:00
Martijn Dekker
64d04e717b Really stop affecting user command history (re: aff63e38)
The fix was incomplete because some tests have to unset HISTFILE,
which reverted them to using ~/.sh_history by default.

src/cmd/ksh93/tests/shtests:
- Instead of setting HISTFILE, set HOME to the temporary directory
  $tmp, so nothing will write to the real user directory and the
  default history file is $tmp/.sh_history.

src/cmd/ksh93/tests/attributes.sh:
- Restore HISTFILE after a test that requires setting HISTFILE=foo.
2020-08-13 23:04:29 +01:00
Martijn Dekker
cadd1a81dc printf %#H: tweak writing unreserved chars (re: 8477d2ce)
src/cmd/ksh93/bltins/print.c:
- If in UTF-8 locale, only bother to check for unreserved char if
  the character is ASCII (< 128), and write unreserved chars with
  a simple stakputc().
2020-08-13 04:51:52 +01:00