From 21202e7b95b2b34446fbac34df67205b3889eed2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 20 Mar 2016 10:30:58 -0700 Subject: 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(). --- ChangeLog | 7 +++++++ Src/Zle/zle_main.c | 35 +++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2f3ecc87..a763ba2d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,13 @@ * m0viefreak: 38145: Doc/Zsh/zle.yo, Src/Zle/zle_params.c: Make isearch and completion suffix variables visible as parameters. +2016-03-20 Barton E. Schaefer + + * 38191: Src/Zle/zle_main.c: in reexpandprompt(), do not free global + pointers until after promptexpand() in case they are referenced from + signal handlers, and do additional re-entrancy checks in case of + window size changes during promptexpand(). + 2016-03-20 Barton E. Schaefer * 38188: Src/pattern.c: signal re-entrancy, maybe 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--; } -- cgit 1.4.1