diff options
author | Barton E. Schaefer <schaefer@zsh.org> | 2016-03-20 10:30:58 -0700 |
---|---|---|
committer | Barton E. Schaefer <schaefer@zsh.org> | 2016-03-21 15:46:59 -0700 |
commit | 21202e7b95b2b34446fbac34df67205b3889eed2 (patch) | |
tree | 7b6925c7af6d5b0aa5e91356839edd7ed4d981e0 /Src | |
parent | 09e991a20a0b27080e978607d6c8f4d14a166803 (diff) | |
download | zsh-21202e7b95b2b34446fbac34df67205b3889eed2.tar.gz zsh-21202e7b95b2b34446fbac34df67205b3889eed2.tar.xz zsh-21202e7b95b2b34446fbac34df67205b3889eed2.zip |
38191: additional re-entrancy checks in reexpandprompt()
Do not free global pointers until after promptexpand() in case they are referenced from signal handlers, and check for window size changes during promptexpand().
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Zle/zle_main.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 6e2bfded8..104e5d6c5 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1856,6 +1856,7 @@ void reexpandprompt(void) { static int reexpanding; + static int looping; if (!reexpanding++) { /* @@ -1866,15 +1867,33 @@ reexpandprompt(void) int local_lastval = lastval; lastval = pre_zle_status; - free(lpromptbuf); - lpromptbuf = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL, - &pmpt_attr); - rpmpt_attr = pmpt_attr; - free(rpromptbuf); - rpromptbuf = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL, - &rpmpt_attr); + do { + /* A new SIGWINCH may arrive while in promptexpand(), causing + * looping to increment. This only happens when a command + * substitution is used in a PROMPT_SUBST prompt, but + * nevertheless keep trying until we see no more changes. + */ + char *new_lprompt, *new_rprompt; + looping = reexpanding; + + new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL, + &pmpt_attr); + free(lpromptbuf); + lpromptbuf = new_lprompt; + + if (looping != reexpanding) + continue; + + rpmpt_attr = pmpt_attr; + new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL, + &rpmpt_attr); + free(rpromptbuf); + rpromptbuf = new_rprompt; + } while (looping != reexpanding); + lastval = local_lastval; - } + } else + looping = reexpanding; reexpanding--; } |