[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