From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25358 invoked by alias); 15 Jun 2017 20:41:03 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 41308 Received: (qmail 18467 invoked from network); 15 Jun 2017 20:41:03 -0000 X-Qmail-Scanner-Diagnostics: from mx.spodhuis.org by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(94.142.241.89):SA:0(-2.3/5.0):. Processed in 0.904822 secs); 15 Jun 2017 20:41:03 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=RCVD_IN_DNSWL_MED, SPF_HELO_PASS,SPF_PASS,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: zsh-workers+phil.pennock@spodhuis.org X-Qmail-Scanner-Mime-Attachments: |signature.asc| X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at spodhuis.org designates 94.142.241.89 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=spodhuis.org; s=d201705; h=Content-Type:MIME-Version:Message-ID:Subject:To: From:Date:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=z5IALjRG5vMjkp1X9AwAgge++lnOwonjHWjdWLMhaDs=; b=G3RKNJdGIfgoXKhngAKU3bKk6Z OkLCeFXir1lMXnZr+VUAocYjxMD6KZye1M/clrlkVOmuvZwBc2Hz0JkTmwUmR/Ktp1HJzlFSPdHLt FyC5rqVxdygwNVszXnzgPdPOW211IXc2xaLYpIcliGUKwELkJhaGr8d//b/yfS+SxcQtR2t7MQz0V 5VNJyx5Be9pKrSK1otc0MmP09ibr; Date: Thu, 15 Jun 2017 16:40:50 -0400 From: Phil Pennock To: zsh-workers@zsh.org Subject: [PATCH] PCRE/NUL: pass NUL in for text, handle NUL out Message-ID: <20170615204050.GA27003@breadbox.private.spodhuis.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="zYM0uCDKw75PZbzx" Content-Disposition: inline OpenPGP: url=https://www.security.spodhuis.org/PGP/keys/0x4D1E900E14C1CC04.asc --zYM0uCDKw75PZbzx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable The regexp itself is always NUL-terminated, so detect embedded NULs and zwarn on their presence. --- Src/Modules/pcre.c | 37 ++++++++++++++++++++++++++----------- Test/V07pcre.ztst | 5 +++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c index 5fd67963d..27191d709 100644 --- a/Src/Modules/pcre.c +++ b/Src/Modules/pcre.c @@ -75,7 +75,7 @@ zpcre_utf8_enabled(void) static int bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func)) { - int pcre_opts =3D 0, pcre_errptr; + int pcre_opts =3D 0, pcre_errptr, target_len; const char *pcre_error; char *target; =20 @@ -89,15 +89,19 @@ bin_pcre_compile(char *nam, char **args, Options ops, U= NUSED(int func)) pcre_opts |=3D PCRE_UTF8; =20 pcre_hints =3D NULL; /* Is this necessary? */ - =20 + if (pcre_pattern) pcre_free(pcre_pattern); =20 target =3D ztrdup(*args); - unmetafy(target, NULL); + unmetafy(target, &target_len); + + if ((int)strlen(target) !=3D target_len) { + zwarnnam(nam, "embedded NULs in PCRE pattern terminate pattern"); + } =20 pcre_pattern =3D pcre_compile(target, pcre_opts, &pcre_error, &pcre_er= rptr, NULL); - =20 + free(target); =20 if (pcre_pattern =3D=3D NULL) @@ -167,7 +171,12 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, ch= ar *matchvar, sprintf(offset_all, "%d %d", ovec[0], ovec[1]); setsparam("ZPCRE_OP", ztrdup(offset_all)); } - match_all =3D metafy(captures[0], -1, META_DUP); + /* + * Result strings can contain embedded NULs; the length of each is the + * difference between the two values in each paired entry in ovec. + * ovec is length 2*(1+capture_list_length) + */ + match_all =3D metafy(captures[0], ovec[1] - ovec[0], META_DUP); setsparam(matchvar, match_all); /* * If we're setting match, mbegin, mend we only do @@ -176,13 +185,16 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, c= har *matchvar, */ if (!want_begin_end || nelem) { char **x, **y; + int vec_off; y =3D &captures[capture_start]; matches =3D x =3D (char **) zalloc(sizeof(char *) * (arrlen(y) + 1)); + vec_off =3D 2; do { if (*y) - *x++ =3D metafy(*y, -1, META_DUP); + *x++ =3D metafy(*y, ovec[vec_off+1]-ovec[vec_off], META_DUP); else *x++ =3D NULL; + vec_off +=3D 2; } while (*y++); setaparam(substravar, matches); } @@ -318,8 +330,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNU= SED(int func)) ovec =3D zalloc(ovecsize*sizeof(int)); =20 plaintext =3D ztrdup(*args); - unmetafy(plaintext, NULL); - subject_len =3D (int)strlen(plaintext); + unmetafy(plaintext, &subject_len); =20 if (offset_start > 0 && offset_start >=3D subject_len) ret =3D PCRE_ERROR_NOMATCH; @@ -351,6 +362,7 @@ cond_pcre_match(char **a, int id) const char *pcre_err; char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=3DNULL; int r =3D 0, pcre_opts =3D 0, pcre_errptr, capcnt, *ov, ovsize; + int lhstr_plain_len, rhre_plain_len; int return_value =3D 0; =20 if (zpcre_utf8_enabled()) @@ -362,8 +374,8 @@ cond_pcre_match(char **a, int id) rhre =3D cond_str(a,1,0); lhstr_plain =3D ztrdup(lhstr); rhre_plain =3D ztrdup(rhre); - unmetafy(lhstr_plain, NULL); - unmetafy(rhre_plain, NULL); + unmetafy(lhstr_plain, &lhstr_plain_len); + unmetafy(rhre_plain, &rhre_plain_len); pcre_pat =3D NULL; ov =3D NULL; ovsize =3D 0; @@ -373,6 +385,9 @@ cond_pcre_match(char **a, int id) =20 switch(id) { case CPCRE_PLAIN: + if ((int)strlen(rhre_plain) !=3D rhre_plain_len) { + zwarn("embedded NULs in PCRE pattern terminate pattern"); + } pcre_pat =3D pcre_compile(rhre_plain, pcre_opts, &pcre_err, &pcre_errptr= , NULL); if (pcre_pat =3D=3D NULL) { zwarn("failed to compile regexp /%s/: %s", rhre, pcre_err); @@ -381,7 +396,7 @@ cond_pcre_match(char **a, int id) pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &cap= cnt); ovsize =3D (capcnt+1)*3; ov =3D zalloc(ovsize*sizeof(int)); - r =3D pcre_exec(pcre_pat, NULL, lhstr_plain, strlen(lhstr_plain), 0,= 0, ov, ovsize); + r =3D pcre_exec(pcre_pat, NULL, lhstr_plain, lhstr_plain_len, 0, 0, = ov, ovsize); /* r < 0 =3D> error; r=3D=3D0 match but not enough size in ov * r > 0 =3D> (r-1) substrings found; r=3D=3D1 =3D> no substrings */ diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst index ad1770712..03cb95791 100644 --- a/Test/V07pcre.ztst +++ b/Test/V07pcre.ztst @@ -131,6 +131,11 @@ >78884; ZPCRE_OP: 25 30 >90210; ZPCRE_OP: 31 36 =20 +# Embedded NULs allowed in plaintext, but not in RE (although \0 as two-ch= ars allowed) + [[ $'a\0bc\0d' =3D~ '^(a\0.)(.+)$' ]] + print "${#MATCH}; ${#match[1]}; ${#match[2]}" +>6; 3; 3 + # Subshell because crash on failure ( setopt re_match_pcre [[ test.txt =3D~ '^(.*_)?(test)' ]] --=20 2.13.1 --zYM0uCDKw75PZbzx Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- iHUEARYIAB0WIQROXBeef/xNv45sEy9REE5mjdBEgQUCWULwxwAKCRBREE5mjdBE gTkbAP40c/Akj2QO5Axm9MKsgOD8EhBNvmVLHeKK3/mg0xWCIwEAsvFGAXzlOaQI 1p4LJ7/aBCEhhVHYRoLwb9TED5vvAQCJAjMEAQEIAB0WIQTGk6A04e1u6VTK4toT 2tmcfkFRnAUCWULw0QAKCRAT2tmcfkFRnA+VD/92yjm+F4KYP880AQujmjsSzqBt AVx+AQPQSTo0QkPk2gjbBIt3a1lMQp0B+MtDOIgVjaAnBViYrq4uXBrr0qWO0/+/ V+sGFZqR40S8ifWie33nxcYL2gfklSxrwRMAgHi+PPBasmMwAsbta2Du9OqAXqI0 E/OHBjMouCpw8MbY0M83U2XoTuwC02ssd5llFOdCdRCdSY6V2uzMjU/mGOtL7hnv duT+5CnkzjNfJImn3SNqWgcTZH57LbhYvvtq1jufycdGfh9O3I4d2nR6fUMlevfD F/L34y+wonnuyxZlpyEThnFLERZOsA0cZ2x4vu2S24NM0iM4P4BoFQvkgKv6nL8c PVGusnZNoWZhdy/M8c33I2bwKZZwXqXieW7bmDWEj+y5kXUW2uhUIZau0lwxcnIn Z+6MlZd4/92trqSgms0+ISYRpa0QR6R2lHo+5PqAuQZfJGthK2mWZpjuol17GxvP pC9b7RK2vfVdwpO3BBIigRwJQhh0GJgJ+YrvqZHP1/CxkhKCt5RgI5Rn93S2bJF8 OGRpVv6ob74MxlU1yhk0a4GL2/QrAVQxzY/uevJebwZibQy0LBhCfyyZo09O7mwq udprn+z8d8pHZ4CNzX6OJYmdpjkJP3M51nQFAOpAe9TnGARLte4Nfa+tQnfrbRxD R8Gw0dMikYiG0a87Wg== =CZaZ -----END PGP SIGNATURE----- --zYM0uCDKw75PZbzx--