about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2016-03-20 10:30:58 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2016-03-21 15:46:59 -0700
commit21202e7b95b2b34446fbac34df67205b3889eed2 (patch)
tree7b6925c7af6d5b0aa5e91356839edd7ed4d981e0 /Src
parent09e991a20a0b27080e978607d6c8f4d14a166803 (diff)
downloadzsh-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.c35
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--;
 }