Subject: Segfault with PCRE (Re: Strange behavior of [[)
From: Mikael Berthe <[email-masked]>
To: [email-masked]
Date: Sat, 23 Apr 2016 11:51:36 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

Hello,

The following lines cause a segfault in zsh on my machines:

  setopt re_match_pcre
  s=test.txt
  [[ $s =~ '^(.*_)?(test)' ]] && echo $match[2]

This occurs only when the first group doesn't match (works fine with
s=1_test.txt).

I think this is related to the patch 37515 (commit 5eae5b58b1b99946),
see below:

* Jun T. <[email-masked]> [2016-01-08 14:09 +0100]:
> pcre.c has the same problem:
> 
> % setopt re_match_pcre
> % [[ $'\ua0' =~ . ]] && echo OK
> (zsh hangs; 100% CPU usage)
> 
> The following is a copy of the patch to regex.c in workers/35448.
> Also added a simple test in V07pcre.ztst.
> 
> diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c

(...)

Here ovec[2] = -1 (because there was no match for '(.**)?'),
and we have ipair = ovec + 2, so leftlen is set to -1 below.

> @@ -219,17 +226,23 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
>  		    ptr = arg;
>  		    offs = 0;
>  		    /* Find the start offset */
> -		    MB_METACHARINIT();
> -		    while (ptr < arg + ipair[0]) {
> +		    MB_CHARINIT();
> +		    leftlen = ipair[0];
> +		    while (leftlen) {
>  			offs++;
> -			ptr += MB_METACHARLEN(ptr);
> +			clen = MB_CHARLEN(ptr, leftlen);
> +			ptr += clen;
> +			leftlen -= clen;
>  		    }

The following patch fixes the segfault for me:

diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index e23ab57..5fd6796 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -228,7 +228,7 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
 		    /* Find the start offset */
 		    MB_CHARINIT();
 		    leftlen = ipair[0];
-		    while (leftlen) {
+		    while (leftlen > 0) {
 			offs++;
 			clen = MB_CHARLEN(ptr, leftlen);
 			ptr += clen;

Regards,
-- 
Mikael