From: phk Date: Sat, 22 Jul 2006 12:00:18 +0000 (+0000) Subject: Implement regexp matching of strings in VCL. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ddb9b77803f4121bc6481e564783838acd63292b;p=varnish Implement regexp matching of strings in VCL. For now we default to REG_EXTENDED, but it might make sense to let the user control this flag and the case sensitivity. Another concern is the stringification of regexps, it may lead to backslash madness. Maybe we should define '...' string types also and do no backslash substitution in those at all. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@559 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 1d53f946..a8f4e80e 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -31,6 +31,7 @@ varnishd_SOURCES = \ cache_vcl.c \ cache_vrt.c \ cache_vrt_acl.c \ + cache_vrt_re.c \ cli_event.c \ hash_simple_list.c \ hash_classic.c \ diff --git a/varnish-cache/bin/varnishd/cache_vrt_re.c b/varnish-cache/bin/varnishd/cache_vrt_re.c new file mode 100644 index 00000000..c7393337 --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_vrt_re.c @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * Runtime support for compiled VCL programs, regexps + * + */ + +#include +#include +#include +#include + +#include "shmlog.h" +#include "vrt.h" +#include "vrt_obj.h" +#include "sbuf.h" +#include "vcl.h" +#include "cache.h" + +void +VRT_re_init(void **rep, const char *re) +{ + regex_t *t; + int i; + + t = calloc(sizeof *t, 1); + assert(t != NULL); + i = regcomp(t, re, REG_EXTENDED | REG_NOSUB); + assert(i == 0); + *rep = t; +} + +void +VRT_re_fini(void *rep) +{ + + if (rep != NULL) + regfree(rep); +} + +int +VRT_re_match(const char *s, void *re) +{ + regex_t *t; + int i; + + t = re; + i = regexec(t, s, 0, NULL, 0); + if (i == 0) + return (1); + assert(i == REG_NOMATCH); + return (0); +} + +int +VRT_re_test(struct sbuf *sb, const char *re) +{ + int i, j; + regex_t t; + char buf[BUFSIZ]; + + memset(&t, 0, sizeof t); + i = regcomp(&t, re, REG_EXTENDED | REG_NOSUB); + if (i == 0) { + regfree(&t); + return (0); + } + j = regerror(i, &t, buf, sizeof buf); + sbuf_printf(sb, "Regexp compilation error:\n\n%s\n\n", buf); + regfree(&t); + return (1); +} diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 73cbcf63..7b507703 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -8,6 +8,7 @@ */ struct sess; +struct sbuf; struct backend; struct VCL_conf; @@ -32,6 +33,12 @@ int VRT_acl_match(struct sess *, const char *, struct vrt_acl *); void VRT_acl_init(struct vrt_acl *); void VRT_acl_fini(struct vrt_acl *); +/* Regexp related */ +void VRT_re_init(void **, const char *); +void VRT_re_fini(void *); +int VRT_re_match(const char *, void *re); +int VRT_re_test(struct sbuf *, const char *); + void VRT_count(struct sess *, unsigned); int VRT_rewrite(const char *, const char *); void VRT_error(struct sess *, unsigned, const char *); diff --git a/varnish-cache/lib/libvcl/vcc_compile.c b/varnish-cache/lib/libvcl/vcc_compile.c index 7b3caf07..66898cb9 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.c +++ b/varnish-cache/lib/libvcl/vcc_compile.c @@ -54,6 +54,7 @@ #include "vcc_priv.h" #include "vcc_compile.h" +#include "vrt.h" #include "libvcl.h" static struct method method_tab[] = { @@ -468,6 +469,28 @@ RateVal(struct tokenlist *tl) Fc(tl, 0, "(%g * %g)", v, sc); } +/*--------------------------------------------------------------------*/ + +static void +vcc_re(struct tokenlist *tl, const char *str, struct token *re) +{ + char buf[32], *p; + + p = EncString(re); + if (VRT_re_test(tl->sb, p)) { + vcc_ErrWhere(tl, re); + return; + } + free(p); + sprintf(buf, "VGC_re_%u", tl->recnt++); + + Fc(tl, 1, "VRT_re_match(%s, %s)\n", str, buf); + Fh(tl, 0, "void *%s;\n", buf); + Fi(tl, 0, "\tVRT_re_init(&%s, %T);\n", buf, re); + Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf); +} + + /*--------------------------------------------------------------------*/ static void @@ -476,10 +499,9 @@ Cond_String(struct var *vp, struct tokenlist *tl) switch (tl->t->tok) { case '~': - Fc(tl, 1, "string_match(%s, ", vp->rname); vcc_NextToken(tl); ExpectErr(tl, CSTR); - Fc(tl, 0, "%T)\n", tl->t); + vcc_re(tl, vp->rname, tl->t); vcc_NextToken(tl); break; case T_EQ: diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h index 0ddfa437..db530258 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.h +++ b/varnish-cache/lib/libvcl/vcc_compile.h @@ -29,6 +29,8 @@ struct tokenlist { int nbackend; TAILQ_HEAD(, proc) procs; struct proc *curproc; + + unsigned recnt; }; enum var_type { diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 4d8870c2..6675de1e 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -474,6 +474,7 @@ vcl_output_lang_h(FILE *f) fputs(" */\n", f); fputs("\n", f); fputs("struct sess;\n", f); + fputs("struct sbuf;\n", f); fputs("struct backend;\n", f); fputs("struct VCL_conf;\n", f); fputs("\n", f); @@ -498,6 +499,12 @@ vcl_output_lang_h(FILE *f) fputs("void VRT_acl_init(struct vrt_acl *);\n", f); fputs("void VRT_acl_fini(struct vrt_acl *);\n", f); fputs("\n", f); + fputs("/* Regexp related */\n", f); + fputs("void VRT_re_init(void **, const char *);\n", f); + fputs("void VRT_re_fini(void *);\n", f); + fputs("int VRT_re_match(const char *, void *re);\n", f); + fputs("int VRT_re_test(struct sbuf *, const char *);\n", f); + fputs("\n", f); fputs("void VRT_count(struct sess *, unsigned);\n", f); fputs("int VRT_rewrite(const char *, const char *);\n", f); fputs("void VRT_error(struct sess *, unsigned, const char *);\n", f);