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

Further robustify .get and .set discipline functions (re: 0a343244) (#368)

This should fix various crashes that remain, at least:
* when running a PS2 discipline at parse time
* when pressing Ctrl+C on a PS2 prompt
* when a special builtin within a discipline throws an error within
  a virtual subshell

src/cmd/ksh93/sh/nvdisc.c:
- In both assign() which handles .set disciplines and lookup()
  which handles .get disciplines, to stop errors in discipline
  functions from wreaking havoc:
  - Save, reinitialise and restore the lexer state in case the
    discipline is run at parse time. This happens with PS2; I'm not
    currently aware of other contexts but that doesn't mean there
    aren't any or that there won't be any. Plus, I determined by
    experimenting that doing this here seems to be the only way to
    make it work reliably. Thankfully the overhead is low.
  - Check the topfd redirection state and run sh_iorestore() if
    needed. Without this, if a special builtin with a redirection
    throws an error in a discipline function, its redirection(s)
    remain permanent. For example, 'trap --bad-option 2>/dev/null'
    in a PS2.get() discipline would kill standard error, including
    all your prompts.

src/cmd/ksh93/sh/io.c: io_prompt():
- Before getting the value of the PS2 prompt, save the stack state
  and restore it after. This stops a PS2.get discipline function
  from corrupting a command substitution that the user is typing.
  Doing this in assign()/lookup() is ineffective, so do it here.

Fixes: https://github.com/ksh93/ksh/issues/347
This commit is contained in:
Martijn Dekker 2021-12-09 06:31:54 +01:00
parent 1f5ad85cd4
commit a2bc49bed1
4 changed files with 61 additions and 11 deletions

View file

@ -889,5 +889,27 @@ w true); echo "Exit status is $?"
u Exit status is 0
!
# err_exit #
tst $LINENO <<"!"
L interrupted PS2 discipline function
# https://github.com/ksh93/ksh/issues/347
d 15
p :test-1:
w PS2.get() { trap --bad-option 2>/dev/null; .sh.value="NOT REACHED"; }
p :test-2:
w echo \$\(
r :test-2: echo \$\(
w echo one \\
r > echo one \\
w two three
r > two three
w echo end
r > echo end
w \)
r > \)
r one two three end
!
# ======
exit $((Errors<125?Errors:125))