diff --git a/1baf0d1f553631ecb641e98f4bf48bc2a44e5b82.patch b/1baf0d1f553631ecb641e98f4bf48bc2a44e5b82.patch
new file mode 100644
index 0000000..1efa0e0
--- /dev/null
+++ b/1baf0d1f553631ecb641e98f4bf48bc2a44e5b82.patch
@@ -0,0 +1,106 @@
+From 1baf0d1f553631ecb641e98f4bf48bc2a44e5b82 Mon Sep 17 00:00:00 2001
+From: Peter Stephenson
+Date: Sun, 15 Dec 2019 19:04:04 +0000
+Subject: [PATCH] 45025: fix re-entrancy problem with memory management in
+ readoutput().
+
+This could cause a signal received during $(...) to corrupt memory.
+---
+ ChangeLog | 6 ++++++
+ Src/exec.c | 61 ++++++++++++++++++++++++++++++++----------------------
+ 2 files changed, 42 insertions(+), 25 deletions(-)
+
+diff --git a/Src/exec.c b/Src/exec.c
+index 9dc91a71e..64eee7dc4 100644
+--- a/Src/exec.c
++++ b/Src/exec.c
+@@ -4646,19 +4646,25 @@ getoutput(char *cmd, int qt)
+ return NULL;
+ }
+
+-/* read output of command substitution */
++/* read output of command substitution
++ *
++ * The file descriptor "in" is closed by the function.
++ *
++ * "qt" indicates if the substitution was in double quotes.
++ *
++ * "readerror", if not NULL, is used to return any error that
++ * occurred during the read.
++ */
+
+ /**/
+ mod_export LinkList
+ readoutput(int in, int qt, int *readerror)
+ {
+ LinkList ret;
+- char *buf, *ptr;
+- int bsiz, c, cnt = 0;
+- FILE *fin;
++ char *buf, *bufptr, *ptr, inbuf[64];
++ int bsiz, c, cnt = 0, readret;
+ int q = queue_signal_level();
+
+- fin = fdopen(in, "r");
+ ret = newlinklist();
+ ptr = buf = (char *) hcalloc(bsiz = 64);
+ /*
+@@ -4670,33 +4676,38 @@ readoutput(int in, int qt, int *readerror)
+ */
+ dont_queue_signals();
+ child_unblock();
+- while ((c = fgetc(fin)) != EOF || errno == EINTR) {
+- if (c == EOF) {
+- errno = 0;
+- clearerr(fin);
+- continue;
+- }
+- if (imeta(c)) {
+- *ptr++ = Meta;
+- c ^= 32;
+- cnt++;
++ for (;;) {
++ readret = read(in, inbuf, 64);
++ if (readret <= 0) {
++ if (readret < 0 && errno == EINTR)
++ continue;
++ else
++ break;
+ }
+- if (++cnt >= bsiz) {
+- char *pp;
+- queue_signals();
+- pp = (char *) hcalloc(bsiz *= 2);
+- dont_queue_signals();
++ for (bufptr = inbuf; bufptr < inbuf + readret; bufptr++) {
++ c = *bufptr;
++ if (imeta(c)) {
++ *ptr++ = Meta;
++ c ^= 32;
++ cnt++;
++ }
++ if (++cnt >= bsiz) {
++ char *pp;
++ queue_signals();
++ pp = (char *) hcalloc(bsiz *= 2);
++ dont_queue_signals();
+
+- memcpy(pp, buf, cnt - 1);
+- ptr = (buf = pp) + cnt - 1;
++ memcpy(pp, buf, cnt - 1);
++ ptr = (buf = pp) + cnt - 1;
++ }
++ *ptr++ = c;
+ }
+- *ptr++ = c;
+ }
+ child_block();
+ restore_queue_signals(q);
+ if (readerror)
+- *readerror = ferror(fin) ? errno : 0;
+- fclose(fin);
++ *readerror = readret < 0 ? errno : 0;
++ close(in);
+ while (cnt && ptr[-1] == '\n')
+ ptr--, cnt--;
+ *ptr = '\0';
diff --git a/zsh.changes b/zsh.changes
index 64ed68c..dad3f0a 100644
--- a/zsh.changes
+++ b/zsh.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Mon Dec 16 15:03:50 UTC 2019 - Ismail Dönmez
+
+- Add 1baf0d1f553631ecb641e98f4bf48bc2a44e5b82.patch to fix a
+ re-entrancy problem.
+
-------------------------------------------------------------------
Mon Dec 16 10:08:27 UTC 2019 - Ismail Dönmez
diff --git a/zsh.spec b/zsh.spec
index 165701b..1247587 100644
--- a/zsh.spec
+++ b/zsh.spec
@@ -43,6 +43,7 @@ Source5: zprofile
Patch1: trim-unneeded-completions.patch
# PATCH-FIX-OPENSUSE zsh-osc-completion.patch -- Fix openSUSE versions in osc completion
Patch2: zsh-osc-completion.patch
+Patch3: 1baf0d1f553631ecb641e98f4bf48bc2a44e5b82.patch
BuildRequires: groff
BuildRequires: libcap-devel
BuildRequires: ncurses-devel
@@ -99,6 +100,7 @@ This package contains the Zsh manual in HTML format.
%patch1 -p1
%endif
%patch2 -p1
+%patch3 -p1
# Remove executable bit
chmod 0644 Etc/changelog2html.pl