[master] 20c820e8e vcc: New REGEX type with expressions
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Fri Jan 15 16:17:07 UTC 2021
commit 20c820e8e59278b8b5a7f4776994a1422f3fdb90
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date: Fri Jan 8 12:34:41 2021 +0100
vcc: New REGEX type with expressions
By introducing a proper REGEX type in VCL we can centralize the regular
expressions literals parsing. The type itself is currently not very
potent since VMODs aren't aware of it, but as a first step it allows
error messages to be improved at compile time.
diff --git a/bin/varnishtest/tests/r00409.vtc b/bin/varnishtest/tests/r00409.vtc
index 1ef578932..6a9db628e 100644
--- a/bin/varnishtest/tests/r00409.vtc
+++ b/bin/varnishtest/tests/r00409.vtc
@@ -1,10 +1,28 @@
varnishtest "Regression test for ticket 409"
-varnish v1 -errvcl {Expected CSTR got '!'} {
- backend b { .host = "${localhost}"; }
+varnish v1 -errvcl {Unknown token '!' when looking for REGEX} {
+ backend be none;
sub vcl_recv {
if ( req.url ~ ! "\.(png|jpg|gif|js|css)$" ) {
return (pass);
}
}
}
+
+varnish v1 -errvcl {Expression has type STRING, expected REGEX} {
+ backend be none;
+ sub vcl_recv {
+ set req.http.regex = "\.(png|jpg|gif|js|css)$";
+ if (req.url ~ req.http.regex) {
+ return (pass);
+ }
+ }
+}
+
+varnish v1 -errvcl {Expression has type STRING, expected REGEX} {
+ backend be none;
+ sub vcl_recv {
+ set req.http.regex = "\?.*";
+ set req.url = regsub(req.url, req.http.regex, "");
+ }
+}
diff --git a/include/vrt.h b/include/vrt.h
index 12cab679d..c88d8cb9e 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -273,6 +273,7 @@ typedef int64_t VCL_INT;
typedef const struct suckaddr * VCL_IP;
typedef const struct vrt_backend_probe * VCL_PROBE;
typedef double VCL_REAL;
+typedef const struct vre * VCL_REGEX;
typedef const struct stevedore * VCL_STEVEDORE;
typedef const struct strands * VCL_STRANDS;
typedef const char * VCL_STRING;
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 376e8f614..1d766ba52 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -771,6 +771,10 @@ vcc_expr5(struct vcc *tl, struct expr **e, vcc_type_t fmt)
ERRCHK(tl);
e1 = vcc_mk_expr(IP, "%s", ip);
ERRCHK(tl);
+ } else if (fmt == REGEX) {
+ e1 = vcc_new_expr(REGEX);
+ vcc_regexp(tl, e1->vsb);
+ AZ(VSB_finish(e1->vsb));
} else {
e1 = vcc_new_expr(STRINGS);
EncToken(e1->vsb, tl->t);
@@ -1075,20 +1079,15 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
static void v_matchproto_(cmp_f)
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
{
+ struct expr *e2;
char buf[128];
- struct vsb vsb;
*e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
vcc_NextToken(tl);
- ExpectErr(tl, CSTR);
- AN(VSB_init(&vsb, buf, sizeof buf));
- VSB_printf(&vsb, "%sVRT_re_match(ctx, \v1, ", cp->emit);
- vcc_regexp(tl, &vsb);
+ vcc_expr0(tl, &e2, REGEX);
ERRCHK(tl);
- VSB_cat(&vsb, ")");
- AZ(VSB_finish(&vsb));
- *e = vcc_expr_edit(tl, BOOL, VSB_data(&vsb), *e, NULL);
- VSB_fini(&vsb);
+ bprintf(buf, "%sVRT_re_match(ctx, \v1, \v2)", cp->emit);
+ *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
}
static void v_matchproto_(cmp_f)
@@ -1342,6 +1341,8 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
t1 = tl->t;
if (fmt->stringform)
vcc_expr_cor(tl, e, STRINGS);
+ else if (fmt == REGEX)
+ vcc_expr4(tl, e, REGEX);
else
vcc_expr_cor(tl, e, fmt);
ERRCHK(tl);
@@ -1457,10 +1458,9 @@ static void v_matchproto_(sym_expr_t)
vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
struct symbol *sym, vcc_type_t fmt)
{
- struct expr *e2;
+ struct expr *e2, *e3;
int all = sym->eval_priv == NULL ? 0 : 1;
char buf[128];
- struct vsb vsb;
(void)t;
(void)fmt;
@@ -1468,15 +1468,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
vcc_expr0(tl, &e2, STRING);
ERRCHK(tl);
SkipToken(tl, ',');
- ExpectErr(tl, CSTR);
-
- AN(VSB_init(&vsb, buf, sizeof buf));
- VSB_printf(&vsb, "VRT_regsub(ctx, %d,\v+\n\v1,\n", all);
- vcc_regexp(tl, &vsb);
+ vcc_expr0(tl, &e3, REGEX);
ERRCHK(tl);
- AZ(VSB_finish(&vsb));
- *e = vcc_expr_edit(tl, STRING, VSB_data(&vsb), e2, NULL);
- VSB_fini(&vsb);
+
+ bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n\v2", all);
+ *e = vcc_expr_edit(tl, STRING, buf, e2, e3);
SkipToken(tl, ',');
vcc_expr0(tl, &e2, STRING);
ERRCHK(tl);
diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c
index 576e55cee..7fcf5078c 100644
--- a/lib/libvcc/vcc_types.c
+++ b/lib/libvcc/vcc_types.c
@@ -151,6 +151,11 @@ const struct type REAL[1] = {{
.multype = REAL,
}};
+const struct type REGEX[1] = {{
+ .magic = TYPE_MAGIC,
+ .name = "REGEX",
+}};
+
static const struct vcc_method stevedore_methods[] = {
#define VRTSTVVAR(nm, vtype, ctype, dval) \
{ VCC_METHOD_MAGIC, vtype, #nm, "VRT_stevedore_" #nm "(\v1)", 0},
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index ce149d8c5..419df3fcb 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -57,9 +57,8 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
int erroroffset;
struct inifin *ifp;
- Expect(tl, CSTR);
- if (tl->err)
- return;
+ assert(tl->t->tok == CSTR);
+
t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
if (t == NULL) {
VSB_printf(tl->sb,
@@ -78,7 +77,6 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
EncToken(ifp->ini, tl->t);
VSB_cat(ifp->ini, ");");
VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf);
- vcc_NextToken(tl);
}
/*
More information about the varnish-commit
mailing list