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

Save $? when discipline triggered without command (#226)

A discipline function could incorrectly influence the value of $?
(exit status of last command) outside its context if it was
triggered without another command being run, e.g. when a prompt
variable is read, or COLUMNS or LINES is set.

Reproducers include:

PS1 prompt:

    $ PS1.get() { true; }
    $ false
    $ echo $?
    0

PS2 prompt:

    $ PS2.get() { return 13; }
    $ \
    > 
    $ echo $?
    13

The set discipline is affected too, e.g. COLUMNS and LINES:

    $ COLUMNS.set() { return 13; }
    $ true
    $ (press return)
    $ echo $?
    13

There are probably other contexts where the shell reads or changes
variables without running commands, allowing their get or set
disciplines to influence $?. So this commit makes ksh save $? for
all .get, .set, .append, and .unset discipline calls.

src/cmd/ksh93/sh/nvdisc.c:
- assign(): Save/restore $? when running a .set/.append/.unset
  discipline function.
- lookup(): Save/restore $? when running a .get discipline.

src/cmd/ksh93/tests/pty.sh:
- Add a regression test for $? after displaying a prompt
  and when setting a LINES.set discipline function.

src/cmd/ksh93/tests/return.sh:
- The above test fails in script form on ksh93u+ and ksh2020, as
  it exposes another form of #117 that occurs after running a
  subshell. Add the above regression test here as well
  (re: 092b90da).

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Johnothan King 2021-03-16 09:13:13 -07:00 committed by GitHub
parent 715b815a28
commit 14352ba0a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 2 deletions

View file

@ -709,5 +709,29 @@ r ^:test-2: fc -lN1\r\n$
r \tdo something\r\n$
!
# err_exit #
tst $LINENO <<"!"
L value of $? after the shell uses a variable with a discipline function
w PS1.get() { true; }; PS2.get() { true; }; false
u PS1.get\(\) \{ true; \}; PS2.get\(\) \{ true; \}; false
w echo "Exit status is: $?"
u Exit status is: 1
w LINES.set() { return 13; }
u LINES.set\(\) \{ return 13; \}
w echo "Exit status is: $?"
u Exit status is: 0
# It's worth noting that the test below will always fail in ksh93u+ and ksh2020,
# even when $PS2 lacks a discipline function (see https://github.com/ksh93/ksh/issues/117).
# After that bug was fixed the test below could still fail if PS2.get() existed.
w false
w (
w exit
w )
w echo "Exit status is: $?"
u Exit status is: 1
!
# ======
exit $((Errors<125?Errors:125))

View file

@ -237,5 +237,8 @@ foo && err_exit "'exit' within 'for' with redirection does not preserve exit sta
foo() ( false; { exit; } 2>&1 )
foo && err_exit "'exit' within { block; } with redirection does not preserve exit status"
foo() { false; (exit); }
foo && err_exit "'exit' within subshell does not preserve exit status"
# ======
exit $((Errors<125?Errors:125))