Commit 20c820e8 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

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.
parent 2065315a
varnishtest "Regression test for ticket 409" varnishtest "Regression test for ticket 409"
varnish v1 -errvcl {Expected CSTR got '!'} { varnish v1 -errvcl {Unknown token '!' when looking for REGEX} {
backend b { .host = "${localhost}"; } backend be none;
sub vcl_recv { sub vcl_recv {
if ( req.url ~ ! "\.(png|jpg|gif|js|css)$" ) { if ( req.url ~ ! "\.(png|jpg|gif|js|css)$" ) {
return (pass); 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, "");
}
}
...@@ -273,6 +273,7 @@ typedef int64_t VCL_INT; ...@@ -273,6 +273,7 @@ typedef int64_t VCL_INT;
typedef const struct suckaddr * VCL_IP; typedef const struct suckaddr * VCL_IP;
typedef const struct vrt_backend_probe * VCL_PROBE; typedef const struct vrt_backend_probe * VCL_PROBE;
typedef double VCL_REAL; typedef double VCL_REAL;
typedef const struct vre * VCL_REGEX;
typedef const struct stevedore * VCL_STEVEDORE; typedef const struct stevedore * VCL_STEVEDORE;
typedef const struct strands * VCL_STRANDS; typedef const struct strands * VCL_STRANDS;
typedef const char * VCL_STRING; typedef const char * VCL_STRING;
......
...@@ -771,6 +771,10 @@ vcc_expr5(struct vcc *tl, struct expr **e, vcc_type_t fmt) ...@@ -771,6 +771,10 @@ vcc_expr5(struct vcc *tl, struct expr **e, vcc_type_t fmt)
ERRCHK(tl); ERRCHK(tl);
e1 = vcc_mk_expr(IP, "%s", ip); e1 = vcc_mk_expr(IP, "%s", ip);
ERRCHK(tl); ERRCHK(tl);
} else if (fmt == REGEX) {
e1 = vcc_new_expr(REGEX);
vcc_regexp(tl, e1->vsb);
AZ(VSB_finish(e1->vsb));
} else { } else {
e1 = vcc_new_expr(STRINGS); e1 = vcc_new_expr(STRINGS);
EncToken(e1->vsb, tl->t); EncToken(e1->vsb, tl->t);
...@@ -1075,20 +1079,15 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp) ...@@ -1075,20 +1079,15 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
static void v_matchproto_(cmp_f) static void v_matchproto_(cmp_f)
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp) cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
{ {
struct expr *e2;
char buf[128]; char buf[128];
struct vsb vsb;
*e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL); *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
vcc_NextToken(tl); vcc_NextToken(tl);
ExpectErr(tl, CSTR); vcc_expr0(tl, &e2, REGEX);
AN(VSB_init(&vsb, buf, sizeof buf));
VSB_printf(&vsb, "%sVRT_re_match(ctx, \v1, ", cp->emit);
vcc_regexp(tl, &vsb);
ERRCHK(tl); ERRCHK(tl);
VSB_cat(&vsb, ")"); bprintf(buf, "%sVRT_re_match(ctx, \v1, \v2)", cp->emit);
AZ(VSB_finish(&vsb)); *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
*e = vcc_expr_edit(tl, BOOL, VSB_data(&vsb), *e, NULL);
VSB_fini(&vsb);
} }
static void v_matchproto_(cmp_f) static void v_matchproto_(cmp_f)
...@@ -1342,6 +1341,8 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt) ...@@ -1342,6 +1341,8 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
t1 = tl->t; t1 = tl->t;
if (fmt->stringform) if (fmt->stringform)
vcc_expr_cor(tl, e, STRINGS); vcc_expr_cor(tl, e, STRINGS);
else if (fmt == REGEX)
vcc_expr4(tl, e, REGEX);
else else
vcc_expr_cor(tl, e, fmt); vcc_expr_cor(tl, e, fmt);
ERRCHK(tl); ERRCHK(tl);
...@@ -1457,10 +1458,9 @@ static void v_matchproto_(sym_expr_t) ...@@ -1457,10 +1458,9 @@ static void v_matchproto_(sym_expr_t)
vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t, vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
struct symbol *sym, vcc_type_t fmt) struct symbol *sym, vcc_type_t fmt)
{ {
struct expr *e2; struct expr *e2, *e3;
int all = sym->eval_priv == NULL ? 0 : 1; int all = sym->eval_priv == NULL ? 0 : 1;
char buf[128]; char buf[128];
struct vsb vsb;
(void)t; (void)t;
(void)fmt; (void)fmt;
...@@ -1468,15 +1468,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t, ...@@ -1468,15 +1468,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
vcc_expr0(tl, &e2, STRING); vcc_expr0(tl, &e2, STRING);
ERRCHK(tl); ERRCHK(tl);
SkipToken(tl, ','); SkipToken(tl, ',');
ExpectErr(tl, CSTR); vcc_expr0(tl, &e3, REGEX);
AN(VSB_init(&vsb, buf, sizeof buf));
VSB_printf(&vsb, "VRT_regsub(ctx, %d,\v+\n\v1,\n", all);
vcc_regexp(tl, &vsb);
ERRCHK(tl); ERRCHK(tl);
AZ(VSB_finish(&vsb));
*e = vcc_expr_edit(tl, STRING, VSB_data(&vsb), e2, NULL); bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n\v2", all);
VSB_fini(&vsb); *e = vcc_expr_edit(tl, STRING, buf, e2, e3);
SkipToken(tl, ','); SkipToken(tl, ',');
vcc_expr0(tl, &e2, STRING); vcc_expr0(tl, &e2, STRING);
ERRCHK(tl); ERRCHK(tl);
......
...@@ -151,6 +151,11 @@ const struct type REAL[1] = {{ ...@@ -151,6 +151,11 @@ const struct type REAL[1] = {{
.multype = REAL, .multype = REAL,
}}; }};
const struct type REGEX[1] = {{
.magic = TYPE_MAGIC,
.name = "REGEX",
}};
static const struct vcc_method stevedore_methods[] = { static const struct vcc_method stevedore_methods[] = {
#define VRTSTVVAR(nm, vtype, ctype, dval) \ #define VRTSTVVAR(nm, vtype, ctype, dval) \
{ VCC_METHOD_MAGIC, vtype, #nm, "VRT_stevedore_" #nm "(\v1)", 0}, { VCC_METHOD_MAGIC, vtype, #nm, "VRT_stevedore_" #nm "(\v1)", 0},
......
...@@ -57,9 +57,8 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name) ...@@ -57,9 +57,8 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
int erroroffset; int erroroffset;
struct inifin *ifp; struct inifin *ifp;
Expect(tl, CSTR); assert(tl->t->tok == CSTR);
if (tl->err)
return;
t = VRE_compile(tl->t->dec, 0, &error, &erroroffset); t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
if (t == NULL) { if (t == NULL) {
VSB_printf(tl->sb, VSB_printf(tl->sb,
...@@ -78,7 +77,6 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name) ...@@ -78,7 +77,6 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
EncToken(ifp->ini, tl->t); EncToken(ifp->ini, tl->t);
VSB_cat(ifp->ini, ");"); VSB_cat(ifp->ini, ");");
VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf); VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf);
vcc_NextToken(tl);
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment