1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
Commit graph

74 commits

Author SHA1 Message Date
Martijn Dekker
064baa372e More misc. tweaks and cleanups
Notable changes:

.github/workflows/ci.yml:
- Run 'bin/package test' on the github runner so we test iffe too.

src/cmd/ksh93/sh/subshell.c:
- sh_assignok was usually called like 'np = sh_assignok(np,0)'. But
  the function never changes np, it just returns the np value
  passed to it, so the assignment is pointless and that function
  can be changed to a void.

src/cmd/ksh93/sh/fault.c: sh_fault():
- Remove check for sh.subshell after sh_isstate(SH_INTERACTIVE). As
  of 48ba6964, it is never set in subshells.
2022-07-14 17:34:08 +02:00
Martijn Dekker
ffee9100d5 Robustify ${.sh.level} scope switching (re: 69d37d5e, e1c41bb2)
Switching the function scope to a parent scope by assigning to
.sh.level (SH_LEVELNOD) leaves the shell in an inconsistent state,
causing invalid-free and/or use-after-free bugs. The intention of
.sh.level was always to temporarily switch scopes inside a DEBUG
trap, so this commit minimises the pitfalls and instability by
imposing some sensible limitations:
1. .sh.level is now a read-only variable except while executing a
   DEBUG trap;
2. while it's writeable, attempts to unset .sh.level or to change
   its attributes are ignored;
3. attempts to set a discipline function for .sh.level are ignored;
4. it is an error to set a level < 0 or > the current scope.

Even more crashing bugs are fixed by simplifiying the handling and
initialisation of .sh.level and by exempting it completely from
virtual subshell scoping (to which it's irrelevant).

TODO: one thing remains: scope corruption and use-after-free happen
when using the '.' command inside a DEBUG trap with ${.sh.level}
changed. Behaviour same as before this commit. To be investigated.

All changed files:
- Consistently use the int16_t type for level values as that is the
  type of its non-pointer storage in SH_LEVELNOD.
- Update .sh.level by using an update_sh_level() macro that assigns
  directly to the node value, then restores the scope if needed.
- To eliminate implicit typecasts, use the same int16_t type (the
  type used by short ints such as SH_LEVELNOD) for all variables
  containing a function and/or dot script level.

src/cmd/ksh93/include/variables.h:
- Add update_sh_level() macro.

src/cmd/ksh93/include/name.h,
src/cmd/ksh93/sh/macro.c:
- Add a nv_nonptr() macro that checks attributes for a non-pointer
  value -- currently only signed or unsigned short integer value,
  accessed via the 's' member of 'union Value' (e.g. np->nvalue.s).
- nv_isnull(): To avoid undefined behaviour, check for attributes
  indicating a non-pointer value before accessing the nvalue.cp
  pointer (re: 5aba0c72).
- varsub(): In the set/unset check, remove the now-redundant
  exception for SH_LEVELNOD.

src/cmd/ksh93/data/variables.c,
src/cmd/ksh93/sh/init.c:
- shtab_variables[]: Make .sh.level a read-only short integer.
- sh_inittree(): To avoid undefined behaviour, do not assign to the
  'union Value' char pointer if the attribute indicates a non-
  pointer short integer value. Instead, the table value is ignored.

src/cmd/ksh93/sh/subshell.c: sh_assignok():
- Never create a subshell scope for SH_LEVELNOD.

src/cmd/ksh93/sh/xec.c:
- Get rid of 'struct Level' and its maxlevel member. This was only
  used in put_level() to check for an out of range assignment, but
  this can be trivially done by checking sh.fn_depth+sh.dot_depth.
- This in turn allows further simplification that reduces init for
  .sh.level to a single nv_disc() call in sh_debug(), so get rid of
  init_level().
- put_level(): Throw a "level out of range" error if assigned a
  wrong level.
- sh_debug():
  - Turn off the NV_RDONLY (read-only) attribute for SH_LEVELNOD
    while executing the DEBUG trap.
  - Restore the current scope when trap execution is finished.
- sh_funct(): Remove all .sh.level handling. POSIX functions (and
  dot scripts) already handle it in b_dot_cmd(), so sh_funct(),
  which is used by both, is the wrong place to do it.
- sh_funscope(): Update .sh.level for ksh syntax functions here
  instead. Also, do not bother to initialise its discipline here,
  as it can now only be changed in a DEBUG trap.

src/cmd/ksh93/bltins/typeset.c: setall():
- When it's not read-only, ignore all attribute changes for
  .sh.level, as changing the attributes would crash the shell.

src/cmd/ksh93/sh/nvdisc.c: nv_setdisc():
- Ignore all attempts to set a discipline function for .sh.level,
  as doing this would crash the shell.

src/cmd/ksh93/bltins/misc.c: b_dot_cmd():
- Bug fix: also update .sh.level when quitting a dot script.

src/cmd/ksh93/sh/name.c:
- _nv_unset():
  - To avoid an inconsistent state, ignore all attempts to unset
    .sh.level.
  - To avoid undefined behaviour, do not zero np->nvalue.cp if
    attributes for np indicate a non-pointer value (the actual bit
    value of a null pointer is not defined by the standard, so
    there is no guarantee that zeroing .cp will zero .s).
- sh_setscope(): For consistency, always set error_info.id (the
  command name for error messages) to the new scope's cmdname.
  Previously this was only done for two calls of this function.
- nv_name(): Fix a crashing bug by checking that np->nvname is a
  non-null pointer before dereferencing it.

src/cmd/ksh93/include/nval.h:
- The NV_UINT16P macro (which is unsigned NV_INT16P) had a typo in
  it, which went unnoticed for many years because it's not directly
  used (though its bit flags are set and used indirectly). Let's
  fix it anyway and keep it for completeness' sake.
2022-07-13 23:11:18 +02:00
Martijn Dekker
ed9053ecfb remove ( simple_command & ) optimisation (re: e3d7bf1d)
I didn't trust this back in e3d7bf1d (which disabled it for
interactive shells) and I trust it less now. In af6a32d1/6b380572,
this was also disabled for virtual subshells as it caused program
flow corruption there. Now, on macOS 10.14.6, a crash occurs when
repeatedly running a command with this optimisation:

$ ksh -c 'for((i=0;i<100;i++));do print -n "$i ";(sleep 1&);done'
0 1 2 3 4 5 6 7 Illegal instruction

Oddly enough it seems that I can only reproduce this crash on macOS
-- not on Linux, OpenBSD, or Solaris. It could be a macOS bug,
particularly given the odd message in the stack trace below.

I've had enough, though. Out it comes. Things now work fine, the
reproducer is fixed on macOS, and it didn't optimise much anyway.

The double-fork issue discussed in e3d7bf1d remains.
________
For future reference, here's an lldb debugger session with a stack
trace. It crashes on calling calloc() (via sh_calloc(), via
sh_newof()) in jobsave_create(). This is not an invalid pointer
problem as we're allocating new memory, so it does look like an OS
bug. The "BUG IN CLIENT OF LIBPLATFORM" message is interesting.

$ lldb -- arch/*/bin/ksh -c 'for((i=0;i<100;i++));do print -n "$i ";(sleep 1&);done'
(lldb) target create "arch/darwin.i386-64/bin/ksh"
Current executable set to 'arch/darwin.i386-64/bin/ksh' (x86_64).
(lldb) settings set -- target.run-args  "-c" "for((i=0;i<100;i++));do print -n \"$i \";(sleep 1&);done"
(lldb) run
error: shell expansion failed (reason: lldb-argdumper exited with error 2). consider launching with 'process launch'.
(lldb) process launch
Process 35038 launched: '/usr/local/src/ksh93/ksh/arch/darwin.i386-64/bin/ksh' (x86_64)
0 1 2 3 4 5 6 7 8 9 Process 35038 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00007fff70deb1c2 libsystem_platform.dylib`_os_unfair_lock_recursive_abort + 23
libsystem_platform.dylib`_os_unfair_lock_recursive_abort:
->  0x7fff70deb1c2 <+23>: ud2

libsystem_platform.dylib`_os_unfair_lock_unowned_abort:
    0x7fff70deb1c4 <+0>:  movl   %edi, %eax
    0x7fff70deb1c6 <+2>:  leaq   0x1a8a(%rip), %rcx        ; "BUG IN CLIENT OF LIBPLATFORM: Unlock of an os_unfair_lock not owned by current thread"
    0x7fff70deb1cd <+9>:  movq   %rcx, 0x361cb16c(%rip)    ; gCRAnnotations + 8
Target 0: (ksh) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x00007fff70deb1c2 libsystem_platform.dylib`_os_unfair_lock_recursive_abort + 23
    frame #1: 0x00007fff70de7c9a libsystem_platform.dylib`_os_unfair_lock_lock_slow + 239
    frame #2: 0x00007fff70daa3bd libsystem_malloc.dylib`tiny_malloc_should_clear + 188
    frame #3: 0x00007fff70daa20f libsystem_malloc.dylib`szone_malloc_should_clear + 66
    frame #4: 0x00007fff70dab444 libsystem_malloc.dylib`malloc_zone_calloc + 99
    frame #5: 0x00007fff70dab3c4 libsystem_malloc.dylib`calloc + 30
    frame #6: 0x000000010003fa5d ksh`sh_calloc(nmemb=1, size=16) at init.c:264:13
    frame #7: 0x000000010004f8a6 ksh`jobsave_create(pid=35055) at jobs.c:272:8
    frame #8: 0x000000010004ed42 ksh`job_reap(sig=20) at jobs.c:363:9
    frame #9: 0x000000010004ff6f ksh`job_waitsafe(sig=20) at jobs.c:511:3
    frame #10: 0x00007fff70de9b5d libsystem_platform.dylib`_sigtramp + 29
    frame #11: 0x00007fff70d39ac4 libsystem_kernel.dylib`__fork + 12
    frame #12: 0x00007fff70c57d80 libsystem_c.dylib`fork + 17
    frame #13: 0x000000010009590d ksh`sh_exec(t=0x0000000101005d30, flags=4) at xec.c:1883:16
    frame #14: 0x0000000100096013 ksh`sh_exec(t=0x0000000101005d30, flags=4) at xec.c:2019:4
    frame #15: 0x0000000100096c4f ksh`sh_exec(t=0x0000000101005a40, flags=5) at xec.c:2213:9
    frame #16: 0x0000000100096013 ksh`sh_exec(t=0x0000000101005a40, flags=5) at xec.c:2019:4
    frame #17: 0x000000010001c23f ksh`exfile(iop=0x0000000100405750, fno=-1) at main.c:603:4
    frame #18: 0x000000010001b23c ksh`sh_main(ac=3, av=0x00007ffeefbff4f0, userinit=0x0000000000000000) at main.c:365:2
    frame #19: 0x0000000100000776 ksh`main(argc=3, argv=0x00007ffeefbff4f0) at pmain.c:45:9
    frame #20: 0x00007fff70bfe3d5 libdyld.dylib`start + 1
2022-06-14 01:32:33 +01:00
Martijn Dekker
2a43cbc3f6 Fix crash on setting attribute to variable with getn discipline
The 'getn' discipline is experimental and undocumented, the only
mention of it being an old mailing list post from David Korn:
https://www.mail-archive.com/ast-users@research.att.com/msg00601.html

But it still should not crash.

$ LC_NUMERIC=C ENV=/./dev/null arch/*/bin/ksh
$ foo.getn() { .sh.value=2.3*4.5; }
$ typeset -F foo
Memory fault

src/cmd/ksh93/sh/nvdisc.c: assign():
- Check that the nvalue union has a non-NULL pointer before
  using it.

Progresses: https://github.com/ksh93/ksh/issues/435
2022-06-07 19:20:43 +01:00
Johnothan King
dccf6b5ea8 Backport ksh93v- regression tests and fix various regression test bugs (#472)
- tests/*.sh: Backported many additional regression tests and test
  fixes from the alpha and beta releases of ksh93v-.

- tests/alias.sh: Avoid trying to add vi to the hash table, as some
  platforms do not provide a vi(1) implementation installed as part
  of the default system. This fixes a regression test failure I was
  getting in one of my Linux virtual machines.

- tests/builtins.sh: Fixed a bug in one of the regression tests that
  caused an incorrect total error count if any of the tests failed.

- tests/sh_match.sh: Fixed a regression test failure on DragonFly
  BSD caused by the diff command printing an extra 'No differences
  encountered' line.
2022-03-11 21:15:55 +01:00
Johnothan King
e87dbebebd Fix use after free bug when using += (re: 75796a9c) (#466)
The previous fix for the += operator introduced a use-after-free
bug that could result in a variable pointing to random garbage:
   $ foo=bar
   $ foo+=_foo true
   $ typeset -p foo
   foo=V V
The use after free issue occurs because when nv_clone creates a
copy of $foo in the true command's invocation-local scope, it does
not duplicate the string $foo points to. As a result, the $foo
variable in the parent scope points to the same string as $foo in
the invocation-local scope, which causes the use after free bug
when cloned $foo variable is freed from memory.

src/cmd/ksh93/sh/nvdisc.c:
- To fix the use after free bug, allow nv_clone to duplicate the
  string with memdup or strdup when no flags are passed.

src/cmd/ksh93/tests/variables.sh:
- Add a regression test for using the += operator with regular
  commands.

src/cmd/ksh93/tests/leaks.sh:
- Add a regression test to ensure the bugfix doesn't introduce any
  memory leaks.
2022-03-11 21:08:57 +01:00
Martijn Dekker
9c313c7fe3 Update copyright years in files changed since 1st Jan 2022 2022-01-30 20:49:04 +00:00
Martijn Dekker
cda661d34c Various cleanups, mostly in regression tests
src/cmd/ksh93/data/variables.sh: shtab_variables[]:
- Remove unused "CSWIDTH" entry. All use of it (including the
  matching CSWIDTHNOD macro) was removed in version 2003-04-22.

src/cmd/ksh93/tests/variables.sh:
- For the tests on the shtab_variables[] variables, read the
  variable names straight from variables.c instead of synching
  the list in the test script, which would surely be forgotten.

src/cmd/ksh93/tests/*.sh:
- Fix a number of mistaken tries to count errors from a subshell.
- Fix miscellaneous minor breakage and typos.
2022-01-24 02:58:25 +00:00
Martijn Dekker
e569f23ef9 bump internal libast version; various minor cleanups
These are minor things I accumulated over the last month or so.

Notable changes:

src/lib/libast/features/api,
src/lib/libast/misc/state.c,
src/lib/libast/comp/conf.tab,
src/cmd/ksh93/include/defs.h:
- Bump internal libast version to 20220101L. We've made a few
  additions to the API, at least pathicase (see 71934570, ca3ec200)
  and astconf_long (see c2ac69b2), so this should have been done
  already. This also updates '/opt/ast/bin/getconf _AST_VERSION'.
- Use AST_VERSION instead of outdated _AST_VERSION.
- In state.c, use AST_VERSION instead of hardcoding the version.

src/cmd/ksh93/sh/xec.c:
- Remove 'restorefd' variable, unused as of 42becab6.
- Remove 'cmdrecurse' function and SH_RUNPROG macro; this was once
  used by a few libcmd commands, but ast-open-archive reveals it's
  unused as of ast 1999-12-25.

src/cmd/ksh93/sh/*.c:
- Where available, use e_dot instead of "." for consistency; it is
  defined as an extern so we might as well use it.

src/cmd/ksh93/tests/*.sh:
- When reporting signal names in fails, include the SIG prefix.
- Fix a broken process hang test in subshell.sh.

src/lib/libast/man/sfdisc.3:
- Removed. The interfaces described here never made it out of AT&T;
  they do not exist in any libast version in ast-open-archive.
  Resolves: https://github.com/ksh93/ksh/issues/426
2022-01-14 19:55:35 +00:00
Martijn Dekker
57ed1efc2c Actually deactivate CDPATH when unsetting it
After 'unset CDPATH', CDPATH continued to work as if nothing
happened. Unsetting it should be a valid way to deactivate it.

This bug is in every ksh93 version.

src/cmd/ksh93/bltins/cd_pwd.c: b_cd():
- Fix a manifest logic error: first check if CDPATH (CDPNOD) is
  unset before assigning to 'cdpath', not the other way around.
  Setting the 'cdpath' pointer is what activates the CDPATH search.
2021-12-29 01:48:55 +00:00
Martijn Dekker
e072e7c170 Fix crash in xtrace while processing here-document (re: d7cada7b)
Depending on the OS, the heredoc.sh regression tests, and possibly
others, still crashed with the -x option (xtrace) on.

Analysis: The lexer crashes in lex_advance(). Something has caused
an inconsistent lexer state, and it happened earlier on, so the
backtrace is useless for figuring out where that happened.

But I think I've found it. It's the sh_mactry() call here:

src/cmd/ksh93/sh/xec.c, lines 2800 to 2807 in f7213f03
2800:   if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
2801:           cp = "+ ";
2802:   else
2803:   {
2804:           sh_offoption(SH_XTRACE);
2805:           cp = sh_mactry(shp,cp);
2806:           sh_onoption(SH_XTRACE);
2807:   }

sh_mactry() needs to parse the contents of $PS4 to perform
expansions and command substitutions in it, which involves the
lexer. If that happens in a here-document, the lexer is in the C
function call stack, in the middle of parsing the here-document.
Result: inconsistent lexer state. Solution: save and restore lexer
state in sh_mactry().

After this commit, all regression tests should pass with the
'-x'/'--xtrace' option in use, with no errors or crashes.

Note for backporters: this fix depends both on on d7cada7b and on
the consistency fix for the Lex_t type's size applied in a7ed5d9f.

src/cmd/ksh93/include/shlex.h:
- Cosmetic fix: remove a copied & pasted backslash. (re: a7ed5d9f)

src/cmd/ksh93/sh/macro.c: sh_mactry():
- Save and restore the lexer state before letting sh_mactrim()
  indirectly parse and execute code.

src/cmd/ksh93/tests/*.sh:
- Turn off xtrace in various command substitutions that contain
  2>&1 redirections, so that the xtrace output is not caught by
  the command substitutions, causing tests to fail incorrectly.
- Turn off xtrace for a few code blocks with 2>&1 redirections,
  stopping xtrace output from being written to standard output.

Resolves: https://github.com/ksh93/ksh/issues/306 (again)
2021-12-27 04:02:25 +00:00
Johnothan King
e6989853bc Fix yet more minor bugs related to the regression tests (#389)
- Redirect error output from the ulimit builtin (re: 3e58851f).
- Fix the test failure for 'cd -eP' on illumos by making a directory
  symlink first, then removing the symlink after cd.
- Fix the test failure for 'getconf -l' on illumos by quoting
  strings with the -q option.
- astconf.c: Only quote strings if the -q option was passed.
- Improve error messages from intermittently failing types.sh tests
2021-12-21 08:01:00 +00:00
Johnothan King
e54001d58b Various minor capitalization and typo fixes (#371)
This commit fixes various minor typos, punctuation errors and
corrects the capitalization of many names.
2021-12-13 01:49:42 +01:00
Martijn Dekker
350e52877b Revert "[1.0 release prep] Remove tilde expansion discipline"
This reverts c0334e32, thereby restoring 936a1939.

After the fixes in 0a343244 and a2bc49be, the tilde expansion
disciplines work nicely, so they can come back to the 1.0 branch.
2021-12-09 07:31:37 +01:00
Johnothan King
beccb93fd4 Fix various compiler warnings and minor issues (#362)
List of changes:
- Fixed some -Wuninitialized warnings and removed some unused variables.

- Removed the unused extern for B_login (re: d8eba9d1).

- The libcmd builtins and the vmalloc memfatal function now handle
  memory errors with 'ERROR_SYSTEM|ERROR_PANIC' for consistency with how
  ksh itself handles out of memory errors.

- Added usage of UNREACHABLE() where it was missing from error handling.

- Extend many variables from short to int to prevent overflows (most
  variables involve file descriptors).

- Backported a ksh2020 patch to fix unused value Coverity issues
  (https://github.com/att/ast/pull/740).

- Note in src/cmd/ksh93/README that ksh compiles with Cygwin on
  Windows 10 and Windows 11, albeit with many test failures.

- Add comments to detail some sections of code. Extensive list of
  commits related to this change:
  ca2443b5, 7e7f1372, 2db9953a, 7003aba4, 6f50ff64, b1a41311,
  222515bf, a0dcdeea, 0aa9e03f, 61437b27, 352e68da, 88e8fa67,
  bc8b36fa, 6e515f1d, 017d088c, 035a4cb3, 588a1ff7, 6d63b57d,
  a2f13c19, 794d1c86, ab98ec65, 1026006d

- Removed a lot of dead ifdef code.

- edit/emacs.c: Hide an assignment to avoid a -Wunused warning. (See
  also https://github.com/att/ast/pull/753, which removed the assignment
  because ksh2020 removed the !SHOPT_MULTIBYTE code.)

- sh/nvdisc.c: The sh_newof macro cannot return a null pointer because
  it will instead cause the shell to exit if memory cannot be allocated.
  That makes the if statement here a no-op, so remove it.

- sh/xec.c: Fixed one unused variable warning in sh_funscope().

- sh/xec.c: Remove a fallthrough comment added in commit ed478ab7
  because the TFORK code doesn't fall through (GCC also produces no
  -Wimplicit-fallthrough warning here).

- data/builtins.c: The cd and pwd man pages state that these builtins
  default to -P if PATH_RESOLVE is 'physical', which isn't accurate:
     $ /opt/ast/bin/getconf PATH_RESOLVE
     physical
     $ mkdir /tmp/dir; ln -s /tmp/dir /tmp/sym
     $ cd /tmp/sym
     $ pwd
     /tmp/sym
     $ cd -P /tmp/sym
     $ pwd
     /tmp/dir
  The behavior described by these man pages isn't specified in the ksh
  man page or by POSIX, so to avoid changing these builtin's behavior
  the inaccurate PATH_RESOLVE information has been removed.

- Mamfiles: Preserve multi-line errors by quoting the $x variable.
  This fix was backported from 93v-.
  (See also <a7e9cc82>.)

- sh/subshell.c: Remove set but not used sp->errcontext variable.
2021-12-09 06:42:59 +01:00
Martijn Dekker
c0334e32a1 [1.0 release prep] Remove tilde expansion discipline
Defining a .sh.tilde.get or .sh.tilde.set discipline function to
extend tilde expansion works well as long as the discipline
function doesn't get interrupted (e.g. with Crtl+C) or produce an
error message. Either of those will cause the shell to become
unstable and crash.

This feature is now removed from the 1.0 branch as it is not ready
for prime time. It can return to a release branch if/when we manage
to fix it on the master branch.

Related: https://github.com/ksh93/ksh/issues/346
2021-11-24 07:46:58 +01:00
Johnothan King
396b388e1f Fix a few issues with $RANDOM seeding in subshells (#339)
This commit fixes an issue I found in the subshell $RANDOM
reseeding code.

The main issue is a performance regression in the shbench fibonacci
benchmark, introduced in commit af6a32d1. Performance dropped in
this benchmark because $RANDOM is always reseeded and restored,
even when it's never used in a subshell. Performance results from
before and after this performance fix (results are on Linux with
CC=gcc and CCFLAGS='-O2 -D_std_malloc'):

  $ ./shbench -b bench/fibonacci.ksh -l 100 ./ksh-0f06a2e ./ksh-af6a32d ./ksh-f31e368 ./ksh-randfix

  benchmarking ./ksh-0f06a2e, ./ksh-af6a32d, ./ksh-f31e368, ./ksh-randfix ...
  *** fibonacci.ksh ***
  # ./ksh-0f06a2e  # Recent version of ksh93u+m
  # ./ksh-af6a32d  # Commit that introduced the regression
  # ./ksh-f31e368  # Commit without the regression
  # ./ksh-randfix  # Ksh93u+m with this patch applied

  -------------------------------------------------------------------------------------------------
  name           ./ksh-0f06a2e        ./ksh-af6a32d        ./ksh-f31e368        ./ksh-randfix
  -------------------------------------------------------------------------------------------------
  fibonacci.ksh  0.481 [0.459-0.515]  0.472 [0.455-0.504]  0.396 [0.380-0.442]  0.407 [0.385-0.439]
  -------------------------------------------------------------------------------------------------

src/cmd/ksh93/include/variables.h,
src/cmd/ksh93/sh/{init,subshell}.c:
- Rather than reseed $RANDOM every time a subshell is created, add
  a sh_save_rand_seed() function that does this only when the
  $RANDOM variable is used in a subshell. This function is called
  by the $RANDOM discipline functions nget_rand() and put_rand().
  As a minor optimization, sh_save_rand_seed doesn't reseed if it's
  called from put_rand().
- Because $RANDOM may have a seed of zero (i.e., RANDOM=0),
  sp->rand_seed isn't enough to tell if $RANDOM has been reseeded.
  Add sp->rand_state for this purpose.
- sh_subshell(): Only restore the former $RANDOM seed and state if
  it is necessary to prevent a subshell leak.

src/cmd/ksh93/tests/variables.sh:
- Add two regression tests for bugs I ran into while making this
  patch.
2021-11-19 08:18:44 +01:00
Martijn Dekker
7ea95b7df3 tests: fix intermittent $RANDOM reseeding fails (re: af6a32d1)
When testing whether subshell $RANDOM reseeding worked, checking
for non-identical numbers is not sufficient. There is no check for
randomly occurring duplicate numbers, nor can there be, because
subshells cannot (or, in the case of virtual subshells, should not)
influence each other or the parent shell.

src/cmd/ksh93/tests/variables.sh:
- Try up to three times, tolerating identical numbers twice.
2021-11-15 21:16:39 +01:00
Martijn Dekker
07eb2040e8 Add regression test (re: e5e1d4b5) 2021-05-19 06:13:30 +02:00
Martijn Dekker
33269cae61 tests/variables.sh: fix ( echo $RANDOM & ) test (re: af6a32d1)
On slower systems it could fail with an arithmetic syntax error
because the output was verified before it had been written.

Also make another test xtrace-proof.
2021-05-03 18:14:34 +01:00
Johnothan King
d5b94a3ff8
Fix some bugs in the regression tests and add more regression tests (#295)
src/cmd/ksh93/tests/{basic.sh,builtins.sh,shtests}:
- Redirect error output from the ulimit builtin to silence irrelevant
  errors in the regression tests (these errors may occur when a
  command such as 'ulimit -t 4' is run before the regression tests).
- Shellquote the error messages from the getconf regression tests.

src/cmd/ksh93/tests/{arrays,io,variables}.sh:
- Backport the ksh2020 regression tests for the following bugs:
  https://github.com/att/ast/issues/23
  https://github.com/att/ast/issues/203
  https://github.com/att/ast/issues/472
  https://github.com/att/ast/issues/492
- Minor fix to POSIX mode regression tests in ksh93v-. In ksh93v-,
  [[ -o ?posix ]] doesn't return an error (because it's implemented
  in the bash mode). However, 'set -o posix' will fail in ksh93v-
  if it's not in bash compatibility mode, which causes this test
  script to exit prematurely.

src/cmd/ksh93/tests/{basic,pty}.sh:
- Add test for https://github.com/att/ast/issues/1461
- The ksh2020 fix for [ -t 1 ] in non-forking command substitutions
  caused the following bug in interactive shells:
    $ ( [ -t 1 ]; echo $? )
    1  # Always fails
  To avoid introducing this bug, this commit adds a regression
  test for it.

src/cmd/ksh93/tests/functions.sh:
- Add test for https://github.com/att/ast/issues/1160
  Put the test to the start of functions.sh (if it's at the end
  of the script, it refuses to fail under ksh2020). Output from
  this regression test when run against ksh2020:
    functions.sh[46]: eval'ing function dumps function body to
    stdout (got $' { eval "bar() { FAILURE; }"; }\n { FAILURE; }')
2021-05-03 06:52:27 +01:00
Martijn Dekker
af6a32d14f
Fix $RANDOM to act consistently in subshells (#294)
This fixes the following:
1. Using $RANDOM in a virtual/non-forked subshell no longer
   influences the reproducible $RANDOM sequence in the parent
   environment.
2. When invoking a subshell $RANDOM is now re-seeded (as mksh and
   bash do) so that invocations in repeated subshells (including
   forked subshells) longer produce identical sequences by default.
3. Program flow corruption that occurred in scripts on executing
   ( ( simple_command & ) ).

src/cmd/ksh93/include/variables.h:
- Move 'struct rand' here as it will be needed in subshell.c. Add
  rand_seed member to save the pseudorandom generator seed. Remove
  the pointer to the shell state as it's redundant.

src/cmd/ksh93/sh/init.c:
- put_rand(): Store given seed in rand_seed while calling srand().
  No longer pointlessly limit the number of possible seeds with the
  RANDMASK bitmask (that mask is to limit the values to 0-32767,
  it should not limit the number of possible sequences to 32768).
- nget_rand(): Instead of using rand(), use rand_r() to update the
  random_seed value. This makes it possible to save/restore the
  current seed of the pseudorandom generator.
- Add sh_reseed_rand() function that reseeds the pseudorandom
  generator by calling srand() with a bitwise-xor combination of
  the current PID, the current time with a granularity of 1/10000
  seconds, and a sequence number that is increased on each
  invocation.
- nv_init(): Set the initial seed using sh_reseed_rand() here
  instead of in sh_main(), as this is where the other struct rand
  members are initialised.

src/cmd/ksh93/sh/main.c: sh_main():
- Remove the srand() call that was replaced by the sh_reseed_rand()
  call in init.c.

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- Upon entering a virtual subshell, save the current $RANDOM seed
  and state, then reseed $RANDOM for the subshell.
- Upon exiting a virtual subshell, restore $RANDOM seed and state
  and reseed the generator using srand() with the restored seed.

src/cmd/ksh93/sh/xec.c: sh_exec():
- When optimizing out a subshell that is the last command, still
  act like a subshell: reseed $RANDOM and increase ${.sh.subshell}.
- Fix a separate bug discovered while implementing this. Do not
  optimize '( simple_command & )' when in a virtual subshell; doing
  this causes program flow corruption.
- When optimizing '( simple_command & )', also reseed $RANDOM and
  increment ${.sh.subshell}.

src/cmd/ksh93/tests/subshell.sh,
src/cmd/ksh93/tests/variables.sh:
- Add various tests for all of the above.

Co-authored-by: Johnothan King <johnothanking@protonmail.com>
Resolves: https://github.com/ksh93/ksh/issues/285
2021-05-03 04:03:46 +01:00
Martijn Dekker
2aad3cab06 Add ksh 93u+m contributors notice to 964 copyright headers 2021-04-26 00:19:31 +01:00
Johnothan King
086d504393
Lots of man page fixes and some other minor fixes (#284)
Noteworthy changes:
- The man pages have been updated to fix a ton of instances of
  runaway underlining (this was done with `sed -i 's/\\f5/\\f3/g'`
  commands). This commit dramatically increased in size because
  of this change.
- The documentation for spawnveg(3) has been extended with
  information about its usage of posix_spawn(3) and vfork(2).
- The documentation for tmfmt(3) has been updated with the changes
  previously made to the man pages for the printf and date builtins
  (though the latter builtin is disabled by default).
- The shell's tracked alias tree (hash table) is now documented in
  the shell(3) man page.
- Removed the commented out regression test for an ERRNO variable
  as the COMPATIBILITY file states it was removed in ksh93.
2021-04-23 22:02:30 +01:00
Johnothan King
2c22ace1e6
Fix LINENO after unsetting it a virtual subshell (#283)
There is a TODO note in variables.sh that notes the value of LINENO
is wrong after a virtual subshell. The following script should
print '6', but the bug causes it to print '1' instead:
  $ cat /tmp/lineno
  #!/bin/ksh
  (
      unset LINENO
      :
  )
  echo $LINENO

This bug started to occur after the bugfix applied in 7b994b6a.
However, that commit is not where the cause of bug was (when that
bugfix is applied to ksh versions 2008-07-25 through 2012-01-01,
$LINENO works fine). Rather, the cause of this bug was introduced
in 93u+ 2012-02-29. In that version, the mp->nvfun pointer was only
copied from np->nvfun if the variable can be freed from memory.
This is what caused 7b994b6a to break $LINENO in subshells, so to
fix this bug the mp->nvfun and np->nvfun must point to the same
object, even when the variable isn't freed from memory.

src/cmd/ksh93/sh/subshell.c: nv_restore():
- Always copy the np->nvfun pointer to mp->nvfun. To prevent
  crashes, the value of np->nvfun->nofree is set to the value given
  by the nofree variable, which is set before _nv_unset. See also
  commit 7e7f1372, which fixed a crash that happened because
  _nv_unset discards the NV_NOFREE flag.

src/cmd/ksh93/tests/variables.sh:
- Remove the workaround for LINENO after a virtual subshell.
- Add a regression test for the value of LINENO when unset in a
  virtual subshell, then used after the subshell. Note that before
  commit 997ad43b LINENO's value was corrupted after being unset in
  a subshell, so the test checks for corruption of the LINENO
  variable (in prior commits LINENO was set to '49' because of the
  previous bug).
2021-04-22 19:16:25 +01:00
Johnothan King
b2a7ec032f
Add LC_TIME to the supported locale variables (#257)
The current version of 93u+m does not have proper support for the
LC_TIME variable. Setting LC_TIME has no effect on printf %T, and
if the locale is invalid no error message is shown:
    $ LC_TIME=ja_JP.UTF-8
    $ printf '%T\n' now
    Wed Apr  7 15:18:13 PDT 2021
    $ LC_TIME=invalid.locale
    $ # No error message

src/cmd/ksh93/data/variables.c,
src/cmd/ksh93/include/variables.h,
src/cmd/ksh93/sh/init.c:
- Add support for the $LC_TIME variable. ksh93v- attempted to add
  support for LC_TIME, but the patch from that version was extended
  because the variable still didn't function correctly.

src/cmd/ksh93/tests/variables.sh:
- Add LC_TIME to the regression tests for LC_* variables.
2021-04-08 13:06:22 +01:00
Martijn Dekker
997ad43bbf Properly fix $LINENO crash on ARM (re: 23b7a163) and other bugs
The typecast fix was insufficient, avoiding the crash only when
compiling with optimisation disabled. The real problem is that
put_lineno() was passed a misaligned pointer, and that the value
didn't actually contain a double but a string. The bug occurred
when restoring the LINENO value upon exiting a virtual subshell.

Thanks to Harald van Dijk for figuring out the fix.

src/cmd/ksh93/sh/subshell.c: nv_restore():
- When restoring a special variable as defined by nv_cover(),
  do not pass either the np->nvflag bits or NV_NOFREE. Why?
  * The np->nvflag bits are not needed. They are also harmful
    because they may include the NV_INTEGER bit. This is set
    when the value is numeric. However, nv_getval() always
    returns the value in string form, converting it if it is
    numeric. So the NV_INTEGER flag should never be passed
    to nv_putval() when it uses the result of nv_getval().
  * According to nval.3, the NV_NOFREE flag stops nv_putval() from
    creating a copy of the value. But this should be unnecessary
    because the earlier _nv_unset(mp,NV_RDONLY|NV_CLONE) should
    ensure there is no previous value. In addition, the NV_NOFREE
    flag triggered another bug that caused the value of SECONDS to
    be corrupted upon restoring it when exiting a virtual subshell.
- When restoring a regular variable, copy the entire nvalue union
  and not just the 'cp' member. In practice this worked because
  no current member of the nvalue union is larger than a pointer.
  However, there is no guarantee it will stay that way.

src/cmd/ksh93/tests/leaks.sh:
- Add disabled test for a memory leak that was discovered in the
  course of dealing with this bug. The fix doesn't introduce or
  influence it. It will have to be dealt with later.

src/cmd/ksh93/tests/locale.sh:
- Add test for restoring locale on leaving virtual subshell.
  https://github.com/ksh93/ksh/issues/253#issuecomment-815290154

src/cmd/ksh93/tests/variables.sh:
- Test against corruption of SECONDS on leaving virtual subshell.
  https://github.com/ksh93/ksh/issues/253#issuecomment-815191052

Co-authored-by: Harald van Dijk <harald@gigawatt.nl>
Progresses: https://github.com/ksh93/ksh/issues/253
2021-04-08 00:56:09 +01:00
Johnothan King
f66a10a8c3
tests/variables.sh: Fix locale tests (#247)
src/cmd/ksh93/tests/variables.sh: LC_* error tests:
- Since operating systems validate locale strings differently,
  try a few different bad locale strings to find one that makes
  setlocale(2) fail, fixing test failures on OpenBSD and Debian.
- Restore warning removed in aed5c6d7, issuing it if none of the
  bad locale strings produce a diagnostic.
- Reenable test for diagnostic message disabled in aed5c6d7.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
2021-03-30 14:53:08 +01:00
Martijn Dekker
936a1939a8
Allow proper tilde expansion overrides (#225)
Until now, when performing any tilde expansion like ~/foo or
~user/foo, ksh added a placeholder built-in command called
'.sh.tilde', ostensibly with the intention to allow users to
override it with a shell function or custom builtin. The multishell
ksh93 repo <https://github.com/multishell/ksh93/> shows this was
added sometime between 2002-06-28 and 2004-02-29. However, it has
never worked and crashed the shell.

This commit replaces that with something that works. Specific tilde
expansions can now be overridden using .set or .get discipline
functions associated with the .sh.tilde variable (see manual,
Discipline Functions).

For example, you can use either of:

.sh.tilde.set()
{
        case ${.sh.value} in
        '~tmp') .sh.value=${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}} ;;
        '~doc') .sh.value=~/Documents ;;
        '~ksh') .sh.value=/usr/local/src/ksh93/ksh ;;
        esac
}

.sh.tilde.get()
{
        case ${.sh.tilde} in
        '~tmp') .sh.value=${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}} ;;
        '~doc') .sh.value=~/Documents ;;
        '~ksh') .sh.value=/usr/local/src/ksh93/ksh ;;
        esac
}

src/cmd/ksh93/include/variables.h,
src/cmd/ksh93/data/variables.c:
- Add SH_TILDENOD for a new ${.sh.tilde} predefined variable.
  It is initially unset.

src/cmd/ksh93/sh/macro.c:
- sh_btilde(): Removed.
- tilde_expand2(): Rewritten. I started out with the tiny version
  of this function from the 2002-06-28 version of ksh. It uses the
  stack instead of sfio, which is more efficient. A bugfix for
  $HOME == '/' was retrofitted so that ~/foo does not become
  //foo instead of /foo. The rest is entirely new code.
     To implement the override functionality, it now checks if
  ${.sh.tilde} has any discipline function associated with it.
  If it does, it assigns the tilde expression to ${.sh.tilde} using
  nv_putval(), triggering the .set discipline, and then reads it
  back using nv_getval(), triggering the .get discipline. The
  resulting value is used if it is nonempty and does not still
  start with a tilde.

src/cmd/ksh93/bltins/typeset.c,
src/cmd/ksh93/tests/builtins.sh:
- Since ksh no longer adds a dummy '.sh.tilde' builtin, remove the
  ad-hoc hack that suppressed it from the output of 'builtin'.

src/cmd/ksh93/tests/tilde.sh:
- Add tests verifying everything I can think of, as well as tests
  for bugs found and fixed during this rewrite.

src/cmd/ksh93/tests/pty.sh:
- Add test verifying that the .sh.tilde.set() discipline does not
  modify the exit status value ($?) when performing tilde expansion
  as part of tab completion.

src/cmd/ksh93/sh.1:
- Instead of "tilde substitution", call the basic mechanism "tilde
  expansion", which is the term used everywhere else (including the
  1995 Bolsky/Korn ksh book).
- Document the new override feature.

Resolves: https://github.com/ksh93/ksh/issues/217
2021-03-17 21:07:14 +00:00
Martijn Dekker
844e6b2410 ...and now make it work with shcomp (re: aed5c6d7) 2021-03-13 19:27:15 +00:00
Martijn Dekker
aed5c6d70a Regress tests: keep common code in one place
src/cmd/ksh93/tests/_common:
- Added. This keeps one common version of 'err_exit', 'warning',
  and other init code.

src/cmd/ksh93/tests/*.sh:
- Source _common as a dot script.
- Remove 50-odd, occasionally slightly different, versions of the
  common code.
- Some minor tweaks.
2021-03-13 18:39:20 +00:00
Johnothan King
59bacfd494
Add more regression tests, mostly from ksh93v- and ksh2020 (#216)
src/cmd/ksh93/tests/arrays.sh,
src/cmd/ksh93/tests/arrays2.sh:
- Backport some regression tests from ksh93v- for associative
  arrays.

src/cmd/ksh93/tests/basic.sh:
- Add ksh93v- regression tests for background process output in
  backtick and shared-state command substitutions as well as
  functions used in command substitutions.

- Add regression tests for using EXIT traps in subshells. In
  ksh93v- and ksh2020 EXIT traps don't work in forked subshells:
  https://github.com/att/ast/issues/1452
- The trap builtin shouldn't segfault after receiving an invalid
  signal name. ksh2020 regression:
  https://github.com/att/ast/issues/1403
- Add a test to make sure invalid flags don't crash ksh.
  ksh2020 regression: https://github.com/att/ast/issues/1284
- Test for an illegal seek error when using the 'join' command with
  process substitutions. ksh93v- regression:
  https://www.mail-archive.com/ast-users@lists.research.att.com/msg00816.html

src/cmd/ksh93/tests/bracket.sh:
- Add some regression tests from ksh93v- for the -eq test operator.

src/cmd/ksh93/tests/builtins.sh:
- Move the regression test for 'exit' in an interactive shell to
  the exit.sh script.
- Test for assignments preceding the command builtin persisting
  after an error. ksh2020 regression:
  https://github.com/att/ast/issues/1402
- The chmod builtin should modify the permissions of all files
  passed to it. ksh2020 regression:
  https://github.com/att/ast/issues/949
- Add regression tests for the cd builtin. In ksh93v- 2013-10-10
  alpha, using cd on a directory without an execute bit doesn't
  cause an error. The test for using cd on a normal file was
  backported from ksh93v-.
- Backport a ksh93v- regression test for the exit status
  from 'kill %'.

src/cmd/ksh93/tests/case.sh:
- Test for a segfault when ksh handles an invalid character class
  in a pattern. ksh2020 regression:
  https://github.com/att/ast/issues/1409

src/cmd/ksh93/tests/exit.sh:
- Add regression tests from ksh2020 for the 'exit' builtin:
  d9491d46

src/cmd/ksh93/tests/io.sh:
- Add a regression test from ksh93v- for a process substitution
  hang. This test fails in the 93v- 2013 alpha but succeeds in
  the 2014 beta.

src/cmd/ksh93/tests/math.sh:
- 'typeset -s foo=30000' adds garbage to $foo in ksh93u+, ksh93v-
  and ksh2020:
  $ typeset -s foo=30000
  $ echo $foo
  5#1430000
  This bug was fixed in commit 88a6baa1, but that commit didn't
  add a regression test for it.

src/cmd/ksh93/tests/variables.sh:
- Add a regression test for $PS4 incorrectly unsetting
  ${.sh.subshell}: https://github.com/att/ast/issues/1092
2021-03-12 16:44:55 +00:00
Martijn Dekker
4a8072e826 Fix ${!foo@} and ${!foo*} to include 'foo' itself in search
These expansions are supposed to yield all variable names beginning
with the indicated prefix. This should include the variable name
that is identical to the prefix (as 'prefix' begins with 'prefix').

This bugfix is backported from the abandoned ksh 93v- beta, so AT&T
intended this change. It also makes ksh work like bash in this.

src/cmd/ksh93/sh/macro.c: varsub(): M_NAMESCAN:
- Check if the prefix itself exists. If so, start with that.

src/cmd/ksh93/tests/variables.sh:
- Add tests for these expansions.

src/cmd/ksh93/sh.1:
- Fix the incomplete documentation of these expansions.

src/cmd/ksh93/COMPATIBILITY:
- Note the change as it's potentially incompatible in corner cases.

Resolves: https://github.com/ksh93/ksh/issues/183
2021-03-09 05:00:04 +00:00
hyenias
5aba0c7251
Fix set/unset state for short integer (typeset -si) (#211)
This commit fixes at least three bugs:
1. When issuing 'typeset -p' for unset variables typeset as short
   integer, a value of 0 was incorrectly diplayed.
2. ${x=y} and ${x:=y} were still broken for short integer types
   (re: 9f2389ed). ${x+set} and ${x:+nonempty} were also broken.
3. A memory fault could occur if typeset -l followed a -s option
   with integers. Additonally, now the last -s/-l wins out as the
   option to utilize instead of it always being short.

src/cmd/ksh93/include/name.h:
- Fix the nv_isnull() macro by removing the direct exclusion of
  short integers from this set/unset test. This breaks few things
  (only ${.sh.subshell} and ${.sh.level}, as far as we can tell)
  while potentially correcting many aspects of short integer use
  (at least bugs 1 and 2 above), as this macro is widely used.
- union Value: add new pid_t *pidp pointer member for PID values
  (see further below).

src/cmd/ksh93/bltins/typeset.c: b_typeset():
- To fix bug 3 above, unset the 'shortint' flag and NV_SHORT
  attribute bit upon encountering the -l optiobn.

*** To fix ${.sh.subshell} to work with the new nv_isnull():

src/cmd/ksh93/sh/defs.h:
- Add new 'realsubshell' member to the shgd (aka shp->gd) struct
  which will be the integer value for ${.sh.subshell}.

src/cmd/ksh93/sh/init.c,
src/cmd/ksh93/data/variables.c:
- Initialize SH_SUBSHELLNOD as a pointer to shgd->realsubshell
  instead of using a short value (.s) directly. Using a pointer
  allows nv_isnull() to return a positive for ${.sh.subshell} as
  a non-null pointer is what it checks for.
- While we're at it, initialize PPIDNOD ($PPID) and SH_PIDNOD
  (${.sh.pid}) using the new pdip union member, which is more
  correct as they are values of type pid_t.

src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- Update the ${.sh.subshell} increases/decreases to refer to
  shgd->realsubshell (a.k.a. shp->gd->realsubshell).

*** To fix ${.sh.level} after changing nv_isnull():

src/cmd/ksh93/sh/macro.c: varsub():
- Add a specific exception for SH_LEVLNOD to the nv_isnull() test,
  so that ${.sh.level} is always considered to be set. Its handling
  throughout the code is too complex/special for a simple fix, so
  we have to special-case it, at least for now.

*** Regression test additions:

src/cmd/ksh93/tests/attributes.sh:
- Add in missing short integer tests and correct the one that
  existed. The -si test now yields 'typeset -x -r -s -i foo'
  instead of 'typeset -x -r -s -i foo=0' which brings it in line
  with all the others.
- Add in some other -l attribute tests for floats. Note, -lX test
  was not added as the size of long double is platform dependent.

src/cmd/ksh93/tests/variables.sh:
- Add tests for ${x=y} and ${x:=y} used on short int variables.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
2021-03-08 04:19:36 +00:00
Martijn Dekker
9f2389ed93 Fix ${x=y} and ${x:=y} for numeric types of x
These POSIX expansions first assign y to x if x is unset or empty,
respectively, and then they yield the value of x. This was not
working on any ksh93 version if x was typeset as numeric (integer
or float) but still unset, as in not assigned a value.

$ unset a; typeset -i a; printf '%q\n' "${a:=42}" "$a"
0
''

Expected output:
42
42

src/cmd/ksh93/sh/macro.c:
- Fix the test for set/unset variable. It was broken because it
  only checked for the existence of the node, which exists after
  'typeset', but did not check if a value had been assigned. This
  additional check needs to be done with the nv_isnull() macro, but
  only for expansions of the regular M_BRACE type. Special
  expansions cannot have an unset state.
- As of commit 95294419, we know that an nv_optimize() call may be
  needed before using nv_isnull() if the shell is compiled with
  SHOPT_OPTIMIZE. Move the nv_optimize() call from that commit
  forward to before the new check that calls nv_isnull(), and only
  bother with it if the type is M_BRACE.

src/cmd/ksh93/tests/variables.sh:
- Add tests for this bug. Test float and integer, and also check
  that ${a=b} and ${a:=b} correctly treat the value of 'b' as an
  arithmetic expression of which the result is assigned to 'a' if
  'a' was typeset as numeric.

src/cmd/ksh93/tests/attributes.sh,
src/cmd/ksh93/tests/comvar.sh,
src/cmd/ksh93/tests/nameref.sh,
src/cmd/ksh93/tests/types.sh:
- Fix a number of tests to report failures correctly.

Resolves: https://github.com/ksh93/ksh/issues/157
2021-03-06 03:56:52 +00:00
Martijn Dekker
5d82004426 Misc regression test fixes
src/cmd/ksh93/tests/basic.sh:
- Fix syntax error (unbalanced single quote) in two -c script
  invocations. It only failed to throw a syntax error due to a
  problematic hack in ksh that may be removed soon.
  See: https://github.com/ksh93/ksh/issues/199

src/cmd/ksh93/tests/builtins.sh,
src/cmd/ksh93/tests/io.sh:
- Redirect standard error on two ksh -i invocations to /dev/null
  to work around the test hanging on AIX.

src/cmd/ksh93/tests/comvario.sh:
- Remove duplicate copyright header.
- Fix warning format.

src/cmd/ksh93/tests/functions.sh:
- Fix the 'TERM signal sent to last process of function kills the
  script' test so that it works on AIX. We cannot rely on grepping
  'ps' output as the external 'sleep' command does not show the
  command name on AIX. Instead, find it by its parent PID.

src/cmd/ksh93/tests/locale.sh,
src/cmd/ksh93/tests/substring.sh:
- Rewrite the very broken multibyte locale tests (two outright
  syntax errors due to unbalanced quotes, and none of the tests
  actually worked).
- Since they set LC_ALL, move them to locale.sh.

src/cmd/ksh93/tests/variables.sh:
- Redirect stderr on some 'ulimit -t unlimited' invocations (which
  fork subshells as the intended side effect) to /dev/null in case
  that exceeds a system-defined limit.
2021-02-28 21:57:38 +00:00
Martijn Dekker
c928046aa9 Fix ${.sh.fun} leaking out of DEBUG trap
The value of the ${.sh.fun} variable, which is supposed to contain
the name of the function currently being executed, leaks out of the
DEBUG trap if it executes a function. Reproducer:

$ fn() { echo "executing the function"; }
$ trap fn DEBUG
$ trap - DEBUG
executing the function
$ echo ${.sh.fun}
fn

${.sh.fun} should be empty outside the function.

Annalysis:

The sh_debug() function in xec.c, which executes the DEBUG trap
action, contains these lines, which are part of restoring the state
after running the trap action with sh_trap():

	nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
 	shp->st = savst;

First the SH_PATHNAMENOD (${.sh.file}) and SH_FUNNAMENOD
(${.sh.fun}) variables get restored from the values in the shell's
scoped information struct (shp->st), but that is done *before*
restoring the parent scope with 'shp->st = savst;'. It should be
done after. Fixing the order is sufficient to fix the bug.

However, I am not convinced that these nv_putval() calls are good
for anything at all. Setting, unsetting, restoring, etc. the
${.sh.fun} and ${.sh.file} variables is already being handled
perfectly well elsewhere in the code for executing functions and
sourcing dot scripts. The DEBUG trap is neither here nor there.
There's no reason for it to get involved with these variables.

I was unable to break anything after simply removing those two
lines. So I strongly suspect this is another case, out of many now,
where a bug in ksh93 is properly fixed by removing some code.

I couldn't get ${.sh.file} to leak similarly -- I think this is
because SH_PATHNAMENOD (and not SH_FUNNOD) is set explicitly in
exfile() in main.c, masking this incorrect restore. It is the only
place where SH_PATHNAMENOD and SH_FUNNOD are not both set.

src/cmd/ksh93/sh/xec.c:
- Remove these two spurious nv_putval() calls.

src/cmd/ksh93/tests/variables.sh:
- Add regression test for leaking ${.sh.fun}.
2021-02-27 01:25:59 +00:00
Johnothan King
2b805f7f1c
Fix many spelling errors and word repetitions (#188)
Many of the errors fixed in this commit are word repetitions
such as 'the the' and minor spelling errors. One formatting
error in the ksh man page has also been fixed.
2021-02-20 03:22:24 +00:00
Martijn Dekker
241b5a4af5 tests/variables.sh: now also test PATH (re: 222515bf) 2021-02-17 18:06:15 +00:00
Lev Kujawski
e2d54b7169
sleep: guarantee sleeping specified time at minimum (#174)
With this patch, the Korn shell can now guarantee that calls to
sleep on systems using the select or poll method always result in
the system clock advancing by that much time, assuming no
interruptions. This compensates for deficiencies in certain
systems, including SCO UnixWare.

Discussion: https://github.com/ksh93/ksh/pull/174

src/lib/libast/tm/tvsleep.c:
- Ensure that at least the time requested to sleep has elapsed
  for the select and poll methods.
- Simplify the logic of calculating the time remaining to
  sleep and handle the case of an argument of greater than
  10e9 nanoseconds being passed to tvsleep.

src/cmd/ksh93/bltins/sleep.c:
- Eliminate the check for EINTR to handle other cases wherein
  we have not slept enough.

src/cmd/ksh93/tests/variables.sh:
- Improve the diagnostic message when the sleep test fails.
- Revise the SECONDS function test to expect that we always
  sleep for at least the time specified.

src/cmd/ksh93/tests/functions.h:
- Redirect ps stderr to /dev/null. UnixWare ps prints an error
  message about not being able to find the controlling terminal
  when shtests output is piped, but we are only using ps to find
  the PID.
2021-02-14 07:27:04 +00:00
Martijn Dekker
2182ecfa08 Fix compile/regress fails on compiling without SHOPT_* options
Many compile-time options were broken so that they could not be
turned off without causing compile errors and/or regression test
failures. This commit now allows the following to be disabled:

SHOPT_2DMATCH    # two dimensional ${.sh.match} for ${var//pat/str}
SHOPT_BGX        # one SIGCHLD trap per completed job
SHOPT_BRACEPAT   # C-shell {...,...} expansions (, required)
SHOPT_ESH        # emacs/gmacs edit mode
SHOPT_HISTEXPAND # csh-style history file expansions
SHOPT_MULTIBYTE  # multibyte character handling
SHOPT_NAMESPACE  # allow namespaces
SHOPT_STATS      # add .sh.stats variable
SHOPT_VSH        # vi edit mode

The following still break ksh when disabled:

SHOPT_FIXEDARRAY # fixed dimension indexed array
SHOPT_RAWONLY    # make viraw the only vi mode
SHOPT_TYPEDEF    # enable typeset type definitions

Compiling without SHOPT_RAWONLY just gives four regression test
failures in pty.sh, but turning off SHOPT_FIXEDARRAY and
SHOPT_TYPEDEF causes compilation to fail. I've managed to tweak the
code to make it compile without those two options, but then dozens
of regression test failures occur, often in things nothing directly
to do with those options. It looks like the separation between the
code for these options and the rest was never properly maintained.
Making it possible to disable SHOPT_FIXEDARRAY and SHOPT_TYPEDEF
may involve major refactoring and testing and may not be worth it.

This commit has far too many tweaks to list. Notables fixes are:

src/cmd/ksh93/data/builtins.c,
src/cmd/ksh93/data/options.c:
- Do not compile in the shell options and documentation for
  disabled features (braceexpand, emacs/gmacs, vi/viraw), so the
  shell is not left with no-op options and inaccurate self-doc.

src/cmd/ksh93/data/lexstates.c:
- Comment the state tables to associte them with their IDs.
- In the ST_MACRO table (sh_lexstate9[]), do not make the S_BRACE
  state for position 123 (ASCII for '{') conditional upon
  SHOPT_BRACEPAT (brace expansion), otherwise disabling this causes
  glob patterns of the form {3}(x) (matching 3 x'es) to stop
  working as well -- and that is ksh globbing, not brace expansion.

src/cmd/ksh93/edit/edit.c: ed_read():
- Fixed a bug: SIGWINCH was not handled by the gmacs edit mode.

src/cmd/ksh93/sh/name.c: nv_putval():
- The -L/-R left/right adjustment options to typeset do not count
  zero-width characters. This is the behaviour with SHOPT_MULTIBYTE
  enabled, regardless of locale. Of course, what a zero-width
  character is depends on the locale, but control characters are
  always considered zero-width. So, to avoid a regression, add some
  fallback code for non-SHOPT_MULTIBYTE builds that skips ASCII
  control characters (as per iscntrl(3)) so they are still
  considered to have zero width.

src/cmd/ksh93/tests/shtests:
- Export the SHOPT_* macros from SHOPT.sh to the tests as
  environment variables, so the tests can check for them and decide
  whether or how to run tests based on the compile-time options
  that the tested binary was presumably compiled with.
- Do not run the C.UTF-8 tests if SHOPT_MULTIBYTE is not enabled.

src/cmd/ksh93/tests/*.sh:
- Add a bunch of checks for SHOPT_* env vars. Since most should
  have a value 0 (off) or 1 (on), the form ((SHOPT_FOO)) is a
  convenient way to use them as arithmetic booleans.

.github/workflows/ci.yml:
- Make GitHub do more testing: run two locale tests (Dutch and
  Japanese UTF-8 locales), then disable all the SHOPTs that we can
  currently disable, recompile ksh, and run the tests again.
2021-02-08 22:02:45 +00:00
Martijn Dekker
32cff97b24 tests/*.sh: fix indentation of warnings 2021-02-04 02:22:46 +00:00
Martijn Dekker
ec0155ee65 tests/variables.sh: tweaks for special and locale variable tests
src/cmd/ksh93/tests/variables.sh:
- Fork the subshell with the test that includes unsetting LINENO
  and changing its type. Otherwise, some side effect of that leaks
  out of the subshell, messing up $LINENO. This is a bug, but it's
  low priority -- we may get to it someday. Marked with a TODO.
- Do the LC_* tests in their own subshell. Skip them if changing
  LANG to an invalid value does not produce a diagnostic message.
  This occurs on OpenBSD and Alpine Linux (with musl libc). It
  looks like their C libraries do not verify the locale, so
  failures here are not a ksh problem; skip the tests in that case.
2021-01-20 05:38:55 +00: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
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: 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
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:
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
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
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