Subject: Re: segfault in completion for configure
From: Bart Schaefer <[email-masked]>
To: [email-masked]
Date: Sat, 12 Mar 2016 09:34:20 -0800
List-Id: Zsh Workers List <zsh-workers.zsh.org>

On Mar 12,  8:20am, Bart Schaefer wrote:
}
} I'm guessing that re-entering pattern matching during the signal handler
} is messing up those globals and leading eventually to the crash.

Try the patch below?  Unfortunately this is likely to slow Jesper's
massive glob a little more.  The right thing would be to factor out
the globals, but there are about 100 references to them so that's
going to be a large code change.

diff --git a/Src/pattern.c b/Src/pattern.c
index 72c7d97..fa9fefb 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -537,9 +537,14 @@ patcompile(char *exp, int inflags, char **endexp)
     Upat pscan;
     char *lng, *strp = NULL;
     Patprog p;
+    int savpatflags, savpatglobflags;
 
     queue_signals();
 
+    /* In case called from a signal handler before queuing */
+    savpatflags = patflags;
+    savpatglobflags = patglobflags;
+
     startoff = sizeof(struct patprog);
     /* Ensure alignment of start of program string */
     startoff = (startoff + sizeof(union upat) - 1) & ~(sizeof(union upat) - 1);
@@ -603,6 +608,8 @@ patcompile(char *exp, int inflags, char **endexp)
 	    /* No, do normal compilation. */
 	    strp = NULL;
 	    if (patcompswitch(0, &flags) == 0) {
+		patflags = savpatflags;
+		patglobflags = savpatglobflags;
 		unqueue_signals();
 		return NULL;
 	    }
@@ -738,6 +745,8 @@ patcompile(char *exp, int inflags, char **endexp)
     if (endexp)
 	*endexp = patparse;
 
+    patflags = savpatflags;
+    patglobflags = savpatglobflags;
     unqueue_signals();
     return p;
 }
@@ -2259,6 +2268,9 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
     char *progstr = (char *)prog + prog->startoff;
     struct patstralloc patstralloc_struct;
 
+    /* In case called from a signal handler */
+    int savpatflags = patflags, savpatglobflags = patglobflags;
+
     if (nump) {
 	maxnpos = *nump;
 	*nump = 0;
@@ -2302,7 +2314,7 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
 	 * Either we are testing against a pure string,
 	 * or we can match anything at all.
 	 */
-	int ret, pstrlen;
+	int pstrlen;
 	char *pstr;
 	if (patstralloc->alloced)
 	{
@@ -2404,8 +2416,6 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
 		}
 	    }
 	}
-
-	return ret;
     } else {
 	int q = queue_signal_level();
 
@@ -2441,6 +2451,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
 	    }
 	}
 	if (!ret) {
+	    patflags = savpatflags;
+	    patglobflags = savpatglobflags;
 	    return 0;
 	}
 
@@ -2596,9 +2608,11 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin,
 	    ret = 0;
 
 	restore_queue_signals(q);
-
-	return ret;
     }
+
+    patflags = savpatflags;
+    patglobflags = savpatglobflags;
+    return ret;
 }
 
 /*