Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nvdisc.c: Fix crash after an error or signal in discipline function #356

Merged
merged 1 commit into from
Dec 2, 2021

Conversation

JohnoKing
Copy link

This patch fixes the crashes experienced when a discipline function (such as .sh.tilde.set() or PS2.get()) exits because of a signal or an error from a special builtin. The crashes were caused by ksh entering an inconsistent state after performing a longjmp away from the assign() and lookup() functions in nvdisc.c. Fixing the crash requires entering a new context, then setting a nonlocal goto with sigsetjmp. Any longjmps that happen while running the discipline function will go back to assign/lookup, allowing ksh to do a proper cleanup afterwards.

I haven't added the regression test for this bug to pty.sh. The test I made does work when ran with the bugfix applied to ksh, but it causes CPU-hungry hangups in unpatched versions of ksh. I couldn't create a good workaround for the hangups, but I'll leave the test here in case anyone manages to fix it:

--- a/src/cmd/ksh93/tests/pty.sh
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -907,5 +907,26 @@ w true); echo "Exit status is $?"
 u Exit status is 0
 !
 
+# err_exit #
+tst $LINENO << "!"
+L crash when discipline functions exit with an error
+# https://github.com/ksh93/ksh/issues/346
+
+w PS1.get() {; printf '$ '; trap --invalid-flag 2>/dev/null; }
+w PS2.get() {; printf '> '; trap --invalid-flag 2>/dev/null; }
+w .sh.tilde.set() {
+w case ${.sh.value} in
+w '~ret') .sh.value='Exit status is' ;;
+w esac
+w trap --invalid-flag 2>/dev/null
+w }
+w echo ~
+w echo ~ret
+s 50
+w echo ~
+w echo ~ret $?
+u Exit status is 0
+!
+
 # ======
 exit $((Errors<125?Errors:125))

Resolves: #346

This patch fixes the crashes experienced when a discipline function
exited because of a signal or an error from a special builtin. The
crashes were caused by ksh entering an inconsistent state after
performing a longjmp away from the assign() and lookup() functions in
nvdisc.c. Fixing the crash requires entering a new context, then setting
a nonlocal goto with sigsetjmp(3). Any longjmps that happen while
running the discipline function will go back to assign/lookup, allowing
ksh to do a proper cleanup afterwards.

Resolves: ksh93#346
@McDutchie
Copy link

Thanks, works for me.

@McDutchie
Copy link

I'll try to take a look at the regression test later. But I think it's nonessential as this seems to be a straightforward fix.

@McDutchie McDutchie merged commit 430e478 into ksh93:master Dec 2, 2021
@JohnoKing JohnoKing deleted the sh-tilde-fix branch December 2, 2021 06:36
McDutchie pushed a commit that referenced this pull request Dec 5, 2021
…356)

This patch fixes the crashes experienced when a discipline function
exited because of a signal or an error from a special builtin. The
crashes were caused by ksh entering an inconsistent state after
performing a longjmp away from the assign() and lookup() functions in
nvdisc.c. Fixing the crash requires entering a new context, then setting
a nonlocal goto with sigsetjmp(3). Any longjmps that happen while
running the discipline function will go back to assign/lookup, allowing
ksh to do a proper cleanup afterwards.

Resolves: #346
JohnoKing added a commit to JohnoKing/ksh that referenced this pull request Feb 16, 2024
This was first reported in att#1472.
Attempting to cancel a heredoc with ^C or ^D can cause ksh to crash with
a segfault, or hangup and fill /tmp with files. Copy of the reproducer:
   $ cat << EOS
   > <Press Ctrl+C or Ctrl+D>

src/cmd/ksh93/sh/main.c:
- Reset the lexer state in an interactive shell if here-document
  creation was cancelled. This patch has been adapted from Solaris:
  https://github.com/oracle/solaris-userland/blob/e478b48/components/ksh93/patches/400-29444429.patch

Due to the nature of this bug, I've skipped adding a regression test as
it risks causing pty to hang up if run against an older release of
ksh93 (cf. ksh93#356).
JohnoKing added a commit to JohnoKing/ksh that referenced this pull request Feb 23, 2024
src/cmd/ksh93/tests/pty.sh:
- Fix test for ksh93#722 by checking for 'Exit status 0' with 'u'.
  As far as I can tell this fixes the CI failure while still catching
  the crash on bugged commits.
- Add a fixed version of the previously unused regression test from
  ksh93#356. Avoiding the CPU hungry lockup only requires spawning a child
  interactive shell for the crash to occur inside of. (This doesn't
  fix the underlying bug in pty, but merely works around it.)
McDutchie pushed a commit that referenced this pull request Mar 23, 2024
src/cmd/ksh93/tests/pty.sh:
- Fix test for #722 by checking for 'Exit status 0' with 'u'. As
  far as I can tell this fixes the CI failure while still catching
  the crash on bugged commits.
- Add a fixed version of the previously unused regression test from
  #356. Avoiding the CPU hungry lockup only requires spawning a
  child interactive shell for the crash to occur inside of. (This
  doesn't fix the underlying bug in pty, but merely works around
  it.)
McDutchie pushed a commit that referenced this pull request Mar 23, 2024
src/cmd/ksh93/tests/pty.sh:
- Fix test for #722 by checking for 'Exit status 0' with 'u'. As
  far as I can tell this fixes the CI failure while still catching
  the crash on bugged commits.
- Add a fixed version of the previously unused regression test from
  #356. Avoiding the CPU hungry lockup only requires spawning a
  child interactive shell for the crash to occur inside of. (This
  doesn't fix the underlying bug in pty, but merely works around
  it.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

.sh.tilde discipline is too brittle
2 participants