We no longer use POSIX style regexes, but rather PCRE regexes. This introduces a hard dependency on libpcre.
Test suite passes, but only lightly tested. --- varnish-cache/bin/varnishd/Makefile.am | 3 +- varnish-cache/bin/varnishd/cache_ban.c | 29 ++++++++------- varnish-cache/bin/varnishd/cache_ban.h | 2 +- varnish-cache/bin/varnishd/cache_vrt_re.c | 48 +++++++++++++----------- varnish-cache/bin/varnishlog/Makefile.am | 3 +- varnish-cache/bin/varnishlog/varnishlog.c | 18 +++++---- varnish-cache/configure.ac | 31 ++++++++++++++++ varnish-cache/include/vrt.h | 2 +- varnish-cache/lib/libvarnishapi/Makefile.am | 4 ++- varnish-cache/lib/libvarnishapi/shmlog.c | 52 +++++++++++++-------------- varnish-cache/lib/libvcl/Makefile.am | 4 ++- varnish-cache/lib/libvcl/vcc_compile.h | 2 +- varnish-cache/lib/libvcl/vcc_parse.c | 2 +- varnish-cache/lib/libvcl/vcc_string.c | 23 ++++++------ 14 files changed, 132 insertions(+), 91 deletions(-) diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index dfdef42..daa389b 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -1,6 +1,6 @@ # $Id$ -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@ sbin_PROGRAMS = varnishd @@ -87,6 +87,7 @@ varnishd_LDADD = \ $(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \ $(top_builddir)/lib/libvcl/libvcl.la \ @JEMALLOC_LDADD@ \ + @PCRE_LIBS@ \ ${DL_LIBS} ${PTHREAD_LIBS} ${NET_LIBS} ${LIBM} ${LIBUMEM} EXTRA_DIST = default.vcl diff --git a/varnish-cache/bin/varnishd/cache_ban.c b/varnish-cache/bin/varnishd/cache_ban.c index 57bdb05..6f6cc0e 100644 --- a/varnish-cache/bin/varnishd/cache_ban.c +++ b/varnish-cache/bin/varnishd/cache_ban.c @@ -50,7 +50,7 @@ SVNID("$Id$") #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <regex.h> +#include <pcre.h> #include "shmlog.h" #include "cli.h" @@ -116,7 +116,7 @@ BAN_Free(struct ban *b) bt = VTAILQ_FIRST(&b->tests); VTAILQ_REMOVE(&b->tests, bt, list); if (bt->flags & BAN_T_REGEXP) - regfree(&bt->re); + pcre_free(&bt->re); if (bt->dst != NULL) free(bt->dst); if (bt->src != NULL) @@ -137,10 +137,13 @@ ban_cond_str(const struct ban_test *bt, const char *p) if (p == NULL) return(!(bt->flags & BAN_T_NOT)); - if (bt->flags & BAN_T_REGEXP) - i = regexec(&bt->re, p, 0, NULL, 0); - else + if (bt->flags & BAN_T_REGEXP) { + i = pcre_exec(bt->re, NULL, p, strlen(p), 0, 0, NULL, 0); + if (i >= 0) + i = 0; + } else { i = strcmp(bt->dst, p); + } if (bt->flags & BAN_T_NOT) return (!i); return (i); @@ -199,15 +202,13 @@ ban_cond_obj_http(const struct ban_test *bt, const struct object *o, static int ban_parse_regexp(struct cli *cli, struct ban_test *bt, const char *a3) { - int i; - char buf[512]; - - i = regcomp(&bt->re, a3, REG_EXTENDED | REG_ICASE | REG_NOSUB); - if (i) { - (void)regerror(i, &bt->re, buf, sizeof buf); - regfree(&bt->re); - VSL(SLT_Debug, 0, "REGEX: <%s>", buf); - cli_out(cli, "%s", buf); + const char *error; + int erroroffset; + + bt->re = pcre_compile(a3, 0, &error, &erroroffset, NULL); + if (bt->re == NULL) { + VSL(SLT_Debug, 0, "REGEX: <%s>", error); + cli_out(cli, "%s", error); cli_result(cli, CLIS_PARAM); return (-1); } diff --git a/varnish-cache/bin/varnishd/cache_ban.h b/varnish-cache/bin/varnishd/cache_ban.h index 58a1ff8..673e5a9 100644 --- a/varnish-cache/bin/varnishd/cache_ban.h +++ b/varnish-cache/bin/varnishd/cache_ban.h @@ -44,7 +44,7 @@ struct ban_test { int flags; #define BAN_T_REGEXP (1 << 0) #define BAN_T_NOT (1 << 1) - regex_t re; + pcre *re; char *dst; char *src; }; diff --git a/varnish-cache/bin/varnishd/cache_vrt_re.c b/varnish-cache/bin/varnishd/cache_vrt_re.c index e91f3c1..0e9052a 100644 --- a/varnish-cache/bin/varnishd/cache_vrt_re.c +++ b/varnish-cache/bin/varnishd/cache_vrt_re.c @@ -35,12 +35,14 @@ SVNID("$Id$") #include <sys/types.h> +#include <syslog.h> + #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> -#include <regex.h> +#include <pcre.h> #include "shmlog.h" #include "vrt.h" @@ -48,14 +50,15 @@ SVNID("$Id$") #include "cache.h" void -VRT_re_init(void **rep, const char *re, int sub) +VRT_re_init(void **rep, const char *re) { - regex_t *t; + pcre *t; + const char *error; + int erroroffset; - t = calloc(sizeof *t, 1); - XXXAN(t); /* This was already check-compiled by the VCL compiler */ - AZ(regcomp(t, re, REG_EXTENDED | REG_ICASE | (sub ? 0 : REG_NOSUB))); + t = pcre_compile(re, 0, &error, &erroroffset, NULL); + AN(t); *rep = t; } @@ -64,23 +67,23 @@ VRT_re_fini(void *rep) { if (rep != NULL) - regfree(rep); + pcre_free(rep); } int VRT_re_match(const char *s, void *re) { - regex_t *t; + pcre *t; int i; if (s == NULL) return (0); AN(re); t = re; - i = regexec(t, s, 0, NULL, 0); - if (i == 0) + i = pcre_exec(t, NULL, s, strlen(s), 0, 0, NULL, 0); + if (i >= 0) return (1); - assert(i == REG_NOMATCH); + assert(i == PCRE_ERROR_NOMATCH); return (0); } @@ -88,8 +91,8 @@ const char * VRT_regsub(const struct sess *sp, int all, const char *str, void *re, const char *sub) { - regmatch_t pm[10]; - regex_t *t; + int ovector[30]; + pcre *t; int i, l; txt res; char *b0; @@ -100,10 +103,11 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re, if (str == NULL) return (""); t = re; - i = regexec(t, str, 10, pm, 0); + memset(&ovector, 0, sizeof(ovector)); + i = pcre_exec(t, NULL, str, strlen(str), 0, 0, ovector, 30); /* If it didn't match, we can return the original string */ - if (i == REG_NOMATCH) + if (i == PCRE_ERROR_NOMATCH) return(str); u = WS_Reserve(sp->http->ws, 0); @@ -112,8 +116,7 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re, do { /* Copy prefix to match */ - Tadd(&res, str, pm[0].rm_so); - + Tadd(&res, str, ovector[0]); for (s = sub ; *s != '\0'; s++ ) { if (*s != '\\' || s[1] == '\0') { if (res.b < res.e) @@ -123,19 +126,20 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re, s++; if (isdigit(*s)) { x = *s - '0'; - l = pm[x].rm_eo - pm[x].rm_so; - Tadd(&res, str + pm[x].rm_so, l); + l = ovector[2*x+1] - ovector[2*x]; + Tadd(&res, str + ovector[2*x], l); continue; } else { if (res.b < res.e) *res.b++ = *s; } } - str += pm[0].rm_eo; + str += ovector[1]; if (!all) break; - i = regexec(t, str, 10, pm, 0); - } while (i != REG_NOMATCH); + memset(&ovector, 0, sizeof(ovector)); + i = pcre_exec(t, NULL, str, strlen(str), 0, 0, ovector, 30); + } while (i != PCRE_ERROR_NOMATCH); /* Copy suffix to match */ l = strlen(str) + 1; diff --git a/varnish-cache/bin/varnishlog/Makefile.am b/varnish-cache/bin/varnishlog/Makefile.am index 85c8b92..2dbd279 100644 --- a/varnish-cache/bin/varnishlog/Makefile.am +++ b/varnish-cache/bin/varnishlog/Makefile.am @@ -1,6 +1,6 @@ # $Id$ -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@ bin_PROGRAMS = varnishlog @@ -13,3 +13,4 @@ varnishlog_LDADD = \ $(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \ $(top_builddir)/lib/libvarnishapi/libvarnishapi.la \ ${PTHREAD_LIBS} + @PCRE_LIBS@ diff --git a/varnish-cache/bin/varnishlog/varnishlog.c b/varnish-cache/bin/varnishlog/varnishlog.c index 4e6245a..4c11981 100644 --- a/varnish-cache/bin/varnishlog/varnishlog.c +++ b/varnish-cache/bin/varnishlog/varnishlog.c @@ -36,7 +36,7 @@ SVNID("$Id$") #include <errno.h> #include <fcntl.h> -#include <regex.h> +#include <pcre.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -80,7 +80,7 @@ static enum shmlogtag last[65536]; #define F_MATCH (1 << 1) static int match_tag = -1; -static regex_t match_re; +static pcre *match_re; static void h_order_finish(int fd) @@ -116,6 +116,7 @@ h_order(void *priv, enum shmlogtag tag, unsigned fd, unsigned len, unsigned spec, const char *ptr) { char type; + int ovector[30]; (void)priv; @@ -132,7 +133,8 @@ h_order(void *priv, enum shmlogtag tag, unsigned fd, unsigned len, assert(ob[fd] != NULL); } if (tag == match_tag && - !regexec(&match_re, ptr, 0, NULL, 0)) + pcre_exec(match_re, NULL, ptr, len, 0, 0, ovector, + sizeof(ovector)/sizeof(ovector[0])) > 0) flg[fd] |= F_MATCH; if ((tag == SLT_BackendOpen || tag == SLT_SessionOpen || @@ -198,6 +200,8 @@ static void do_order(struct VSL_data *vd, int argc, char **argv) { int i; + const char *error; + int erroroffset; if (argc == 2) { match_tag = name2tag(argv[0]); @@ -205,11 +209,9 @@ do_order(struct VSL_data *vd, int argc, char **argv) fprintf(stderr, "Tag \"%s\" unknown\n", argv[0]); exit(2); } - i = regcomp(&match_re, argv[1], REG_EXTENDED | REG_NOSUB); - if (i) { - char buf[BUFSIZ]; - regerror(i, &match_re, buf, sizeof buf); - fprintf(stderr, "%s\n", buf); + match_re = pcre_compile(argv[1], 0, &error, &erroroffset, NULL); + if (match_re == NULL) { + fprintf(stderr, "Invalid regex: %s\n", error); exit(2); } } diff --git a/varnish-cache/configure.ac b/varnish-cache/configure.ac index 5c2d67f..4fc88a5 100644 --- a/varnish-cache/configure.ac +++ b/varnish-cache/configure.ac @@ -75,6 +75,37 @@ AC_SUBST(NET_LIBS) AC_CHECK_LIBM AC_SUBST(LIBM) +PKG_PROG_PKG_CONFIG +if test -n $PKG_CONFIG; then + PKG_CHECK_MODULES([PCRE], [libpcre]) +else + AC_CHECK_PROG(PCRE_CONFIG, pcre-config, pcre-config) + AC_ARG_WITH(pcre-config, + AS_HELP_STRING([--with-pcre-config=PATH], + [Location of PCRE pcre-config (auto)]), + [pcre_config="$withval"], + [pcre_config=""]) + + if test "x$pcre_config" != "x" ; then + AC_MSG_CHECKING(for $pcre_config) + + if test -f $pcre_config ; then + PCRE_CONFIG=$pcre_config + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no - searching PATH) + fi + fi + if test "x$PCRE_CONFIG" = "x"; then + AC_CHECK_PROGS(PCRE_CONFIG, pcre-config) + fi + PCRE_CFLAGS=`$PCRE_CONFIG --cflags` + PCRE_LIBS=`$PCRE_CONFIG --libs` +fi +AC_SUBST(PCRE_CFLAGS) +AC_SUBST(PCRE_LIBS) + + # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 150db3c..17dbf25 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -136,7 +136,7 @@ struct vrt_ref { void VRT_acl_log(const struct sess *, const char *msg); /* Regexp related */ -void VRT_re_init(void **, const char *, int sub); +void VRT_re_init(void **, const char *); void VRT_re_fini(void *); int VRT_re_match(const char *, void *re); const char *VRT_regsub(const struct sess *sp, int all, const char *, diff --git a/varnish-cache/lib/libvarnishapi/Makefile.am b/varnish-cache/lib/libvarnishapi/Makefile.am index b109811..4210d46 100644 --- a/varnish-cache/lib/libvarnishapi/Makefile.am +++ b/varnish-cache/lib/libvarnishapi/Makefile.am @@ -1,6 +1,8 @@ # $Id$ -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@ + +LIBS = @PCRE_LIBS@ lib_LTLIBRARIES = libvarnishapi.la diff --git a/varnish-cache/lib/libvarnishapi/shmlog.c b/varnish-cache/lib/libvarnishapi/shmlog.c index 37be28a..78be38a 100644 --- a/varnish-cache/lib/libvarnishapi/shmlog.c +++ b/varnish-cache/lib/libvarnishapi/shmlog.c @@ -40,7 +40,7 @@ SVNID("$Id$") #include <errno.h> #include <fcntl.h> #include <limits.h> -#include <regex.h> +#include <pcre.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -84,8 +84,8 @@ struct VSL_data { #define M_SELECT (1 << 3) int regflags; - regex_t *regincl; - regex_t *regexcl; + pcre *regincl; + pcre *regexcl; unsigned long skip; unsigned long keep; @@ -170,7 +170,7 @@ VSL_New(void) assert(VSL_S_BACKEND == M_BACKEND); vd = calloc(sizeof *vd, 1); assert(vd != NULL); - vd->regflags = REG_EXTENDED | REG_NOSUB; + vd->regflags = 0; vd->magic = VSL_MAGIC; vd->fd = -1; return (vd); @@ -272,9 +272,9 @@ int VSL_NextLog(struct VSL_data *vd, unsigned char **pp) { unsigned char *p; - regmatch_t rm; unsigned u, l; int i; + int ovector[30]; CHECK_OBJ_NOTNULL(vd, VSL_MAGIC); while (1) { @@ -315,19 +315,23 @@ VSL_NextLog(struct VSL_data *vd, unsigned char **pp) if (vd->c_opt && !(vd->map[u] & M_CLIENT)) continue; if (vd->regincl != NULL) { - rm.rm_so = 0; - rm.rm_eo = l; - i = regexec(vd->regincl, - (char *)p + SHMLOG_DATA, 1, &rm, 0); - if (i == REG_NOMATCH) + i = pcre_exec(vd->regincl, + NULL, /* We didn't study the pattern*/ + (char *)p + SHMLOG_DATA, + SHMLOG_LEN(p) - SHMLOG_DATA, /* Length */ + 0, 0, ovector, + sizeof(ovector)/sizeof(ovector[0])); + if (i == PCRE_ERROR_NOMATCH) continue; } if (vd->regexcl != NULL) { - rm.rm_so = 0; - rm.rm_eo = l; - i = regexec(vd->regexcl, - (char *)p + SHMLOG_DATA, 1, &rm, 0); - if (i != REG_NOMATCH) + i = pcre_exec(vd->regincl, + NULL, /* We didn't study the pattern*/ + (char *)p + SHMLOG_DATA, + SHMLOG_LEN(p) - SHMLOG_DATA, /* Length */ + 0, 0, ovector, + sizeof(ovector)/sizeof(ovector[0])); + if (i != PCRE_ERROR_NOMATCH) continue; } *pp = p; @@ -412,9 +416,9 @@ vsl_r_arg(struct VSL_data *vd, const char *opt) static int vsl_IX_arg(struct VSL_data *vd, const char *opt, int arg) { - int i; - regex_t **rp; - char buf[BUFSIZ]; + pcre **rp; + const char *error; + int erroroffset; CHECK_OBJ_NOTNULL(vd, VSL_MAGIC); if (arg == 'I') @@ -425,15 +429,9 @@ vsl_IX_arg(struct VSL_data *vd, const char *opt, int arg) fprintf(stderr, "Option %c can only be given once", arg); return (-1); } - *rp = calloc(sizeof(regex_t), 1); + *rp = pcre_compile(opt, vd->regflags, &error, &erroroffset, NULL); if (*rp == NULL) { - perror("malloc"); - return (-1); - } - i = regcomp(*rp, opt, vd->regflags); - if (i) { - regerror(i, *rp, buf, sizeof buf); - fprintf(stderr, "%s", buf); + fprintf(stderr, "Illegal regex: %s\n", error); return (-1); } return (1); @@ -547,7 +545,7 @@ VSL_Arg(struct VSL_data *vd, int arg, const char *opt) case 'i': case 'x': return (vsl_ix_arg(vd, opt, arg)); case 'r': return (vsl_r_arg(vd, opt)); case 'I': case 'X': return (vsl_IX_arg(vd, opt, arg)); - case 'C': vd->regflags = REG_ICASE; return (1); + case 'C': vd->regflags = PCRE_CASELESS; return (1); case 's': return (vsl_s_arg(vd, opt)); case 'k': return (vsl_k_arg(vd, opt)); default: diff --git a/varnish-cache/lib/libvcl/Makefile.am b/varnish-cache/lib/libvcl/Makefile.am index 4bb2e4b..6d98e43 100644 --- a/varnish-cache/lib/libvcl/Makefile.am +++ b/varnish-cache/lib/libvcl/Makefile.am @@ -1,6 +1,8 @@ # $Id$ -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@ + +LDADD = @PCRE_LIBS@ lib_LTLIBRARIES = libvcl.la diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h index 256da13..be44bfb 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.h +++ b/varnish-cache/lib/libvcl/vcc_compile.h @@ -198,7 +198,7 @@ unsigned vcc_UintVal(struct tokenlist *tl); double vcc_DoubleVal(struct tokenlist *tl); /* vcc_string.c */ -char *vcc_regexp(struct tokenlist *tl, int sub); +char *vcc_regexp(struct tokenlist *tl); int vcc_StringVal(struct tokenlist *tl); void vcc_ExpectedStringval(struct tokenlist *tl); diff --git a/varnish-cache/lib/libvcl/vcc_parse.c b/varnish-cache/lib/libvcl/vcc_parse.c index d6079f2..ef2b09a 100644 --- a/varnish-cache/lib/libvcl/vcc_parse.c +++ b/varnish-cache/lib/libvcl/vcc_parse.c @@ -225,7 +225,7 @@ Cond_String(const struct var *vp, struct tokenlist *tl) tl->t->tok == '~' ? "" : "!"); vcc_NextToken(tl); ExpectErr(tl, CSTR); - p = vcc_regexp(tl, 0); + p = vcc_regexp(tl); ERRCHK(tl); vcc_NextToken(tl); Fb(tl, 1, "%s, %s)\n", vp->rname, p); diff --git a/varnish-cache/lib/libvcl/vcc_string.c b/varnish-cache/lib/libvcl/vcc_string.c index 564e3da..7fe34b7 100644 --- a/varnish-cache/lib/libvcl/vcc_string.c +++ b/varnish-cache/lib/libvcl/vcc_string.c @@ -34,7 +34,7 @@ SVNID("$Id$") #include <stdio.h> #include <string.h> -#include <regex.h> +#include <pcre.h> #include "vsb.h" @@ -47,26 +47,25 @@ SVNID("$Id$") /*--------------------------------------------------------------------*/ char * -vcc_regexp(struct tokenlist *tl, int sub) +vcc_regexp(struct tokenlist *tl) { char buf[BUFSIZ], *p; - regex_t t; - int i; + pcre *t; + const char *error; + int erroroffset; Expect(tl, CSTR); if (tl->err) return (NULL); memset(&t, 0, sizeof t); - i = regcomp(&t, tl->t->dec, REG_EXTENDED | (sub ? 0 : REG_NOSUB)); - if (i != 0) { - (void)regerror(i, &t, buf, sizeof buf); + t = pcre_compile(tl->t->dec, 0, &error, &erroroffset, NULL); + if (t == NULL) { vsb_printf(tl->sb, - "Regexp compilation error:\n\n%s\n\n", buf); + "Regexp compilation error:\n\n%s\n\n", error); vcc_ErrWhere(tl, tl->t); - regfree(&t); return (NULL); } - regfree(&t); + pcre_free(t); sprintf(buf, "VGC_re_%u", tl->recnt++); p = TlAlloc(tl, strlen(buf) + 1); strcpy(p, buf); @@ -74,7 +73,7 @@ vcc_regexp(struct tokenlist *tl, int sub) Fh(tl, 0, "static void *%s;\n", buf); Fi(tl, 0, "\tVRT_re_init(&%s, ",buf); EncToken(tl->fi, tl->t); - Fi(tl, 0, ", %d);\n", sub); + Fi(tl, 0, ");\n"); Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf); return (p); } @@ -108,7 +107,7 @@ vcc_regsub(struct tokenlist *tl, int all) Expect(tl, CSTR); if (tl->err) return (0); - p = vcc_regexp(tl, 1); + p = vcc_regexp(tl); vcc_NextToken(tl); Fb(tl, 0, ", %s, ", p); -- 1.6.3.3 -- Tollef Fog Heen Redpill Linpro -- Changing the game! t: +47 21 54 41 73 _______________________________________________ varnish-dev mailing list varnish-dev@projects.linpro.no http://projects.linpro.no/mailman/listinfo/varnish-dev