Switch to VRE_capture()

needs the patch from https://github.com/varnishcache/varnish-cache/pull/3725

This also moves the check for subgroups to compile time.
parent 685aa25e
......@@ -12,7 +12,7 @@ varnish v1 -vcl+backend {
import re from "${vmod_topbuild}/src/.libs/libvmod_re.so";
sub vcl_init {
new barbaz = re.regex("(bar)(baz)");
new barbaz = re.regex("(bar)(baz)");
}
sub vcl_backend_response {
......
varnishtest "limit to backrefs 0 to 10"
server s1 {
rxreq
txresp -hdr "Foo: 12345678901" -hdr "Bar: 123456789012" -body "1111\n"
} -start
varnish v1 -vcl+backend {
import re from "${vmod_topbuild}/src/.libs/libvmod_re.so";
sub vcl_init {
new tendots = re.regex("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
new moredots = re.regex("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
}
sub vcl_backend_response {
if (tendots.match(beresp.http.foo)) {
set beresp.http.foo0 = tendots.backref(0, "error0");
set beresp.http.foo1 = tendots.backref(1, "error1");
set beresp.http.foo2 = tendots.backref(2, "error2");
set beresp.http.foo3 = tendots.backref(3, "error3");
set beresp.http.foo4 = tendots.backref(4, "error4");
set beresp.http.foo5 = tendots.backref(5, "error5");
set beresp.http.foo6 = tendots.backref(6, "error6");
set beresp.http.foo7 = tendots.backref(7, "error7");
set beresp.http.foo8 = tendots.backref(8, "error8");
set beresp.http.foo9 = tendots.backref(9, "error9");
set beresp.http.foo10 = tendots.backref(10, "error10");
set beresp.http.foo11 = tendots.backref(11, "fallback");
} else {
set beresp.status = 999;
}
if (moredots.match(beresp.http.bar)) {
set beresp.http.bar0 = moredots.backref(0, "error0");
set beresp.http.bar1 = moredots.backref(1, "error1");
set beresp.http.bar2 = moredots.backref(2, "error2");
set beresp.http.bar3 = moredots.backref(3, "error3");
set beresp.http.bar4 = moredots.backref(4, "error4");
set beresp.http.bar5 = moredots.backref(5, "error5");
set beresp.http.bar6 = moredots.backref(6, "error6");
set beresp.http.bar7 = moredots.backref(7, "error7");
set beresp.http.bar8 = moredots.backref(8, "error8");
set beresp.http.bar9 = moredots.backref(9, "error9");
set beresp.http.bar10 = moredots.backref(10, "error10");
set beresp.http.bar11 = moredots.backref(11, "fallback");
} else {
set beresp.status = 999;
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.foo0 == "1234567890"
expect resp.http.foo1 == "1"
expect resp.http.foo2 == "2"
expect resp.http.foo3 == "3"
expect resp.http.foo4 == "4"
expect resp.http.foo5 == "5"
expect resp.http.foo6 == "6"
expect resp.http.foo7 == "7"
expect resp.http.foo8 == "8"
expect resp.http.foo9 == "9"
expect resp.http.foo10 == "0"
expect resp.http.foo11 == "fallback"
expect resp.http.bar0 == "12345678901"
expect resp.http.bar1 == "1"
expect resp.http.bar2 == "2"
expect resp.http.bar3 == "3"
expect resp.http.bar4 == "4"
expect resp.http.bar5 == "5"
expect resp.http.bar6 == "6"
expect resp.http.bar7 == "7"
expect resp.http.bar8 == "8"
expect resp.http.bar9 == "9"
expect resp.http.bar10 == "0"
expect resp.http.bar11 == "fallback"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod re: backref \d+ out of range$}
expect * = VCL_Error {^vmod re: capturing substrings exceed max \d+}
expect * = VCL_Error {^vmod re: backref \d+ out of range$}
expect * = End
} -run
......@@ -52,37 +52,12 @@ varnish v1 -vcl+backend {
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.foo0 == "1234567890"
expect resp.http.foo1 == "1"
expect resp.http.foo2 == "2"
expect resp.http.foo3 == "3"
expect resp.http.foo4 == "4"
expect resp.http.foo5 == "5"
expect resp.http.foo6 == "6"
expect resp.http.foo7 == "7"
expect resp.http.foo8 == "8"
expect resp.http.foo9 == "9"
expect resp.http.foo10 == "0"
expect resp.http.foo11 == "fallback"
expect resp.http.bar0 == "12345678901"
expect resp.http.bar1 == "1"
expect resp.http.bar2 == "2"
expect resp.http.bar3 == "3"
expect resp.http.bar4 == "4"
expect resp.http.bar5 == "5"
expect resp.http.bar6 == "6"
expect resp.http.bar7 == "7"
expect resp.http.bar8 == "8"
expect resp.http.bar9 == "9"
expect resp.http.bar10 == "0"
expect resp.http.bar11 == "fallback"
expect resp.status == 999
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod re: backref \d+ out of range$}
expect * = VCL_Error {^vmod re: capturing substrings exceed max \d+}
expect * = VCL_Error {^vmod re: backref \d+ out of range$}
expect * = VCL_Error {^vmod re: error compiling.*too many capturing}
expect * = VCL_Error {^vmod re: error compiling.*too many capturing}
expect * = End
} -run
......@@ -43,7 +43,6 @@
#include "vcc_if.h"
#define MAX_MATCHES 11
#define MAX_OV ((MAX_MATCHES) * 2)
struct vmod_re_regex {
unsigned magic;
......@@ -56,7 +55,7 @@ typedef struct ov_s {
unsigned magic;
#define OV_MAGIC 0x844bfa39
const char *subject;
int ovector[MAX_OV];
txt groups[MAX_MATCHES];
} ov_t;
static void
......@@ -156,12 +155,8 @@ match(VRT_CTX, const vre_t *vre, VCL_STRING subject, struct vmod_priv *task,
const struct vre_limits *vre_limits)
{
ov_t *ov;
int i, r = 0, s, nov[MAX_OV];
int i, s;
size_t cp;
pcre2_match_context *re_ctx;
pcre2_match_data *data;
pcre2_code *re;
PCRE2_SIZE *ovector;
AN(vre);
if (subject == NULL)
......@@ -176,41 +171,23 @@ match(VRT_CTX, const vre_t *vre, VCL_STRING subject, struct vmod_priv *task,
task->len = -1;
AZ(task->methods);
ov = (ov_t *) task->priv;
ov->magic = OV_MAGIC;
INIT_OBJ(ov, OV_MAGIC);
}
else {
AN(WS_Allocated(ctx->ws, task->priv, sizeof(*ov)));
CAST_OBJ_NOTNULL(ov, task->priv, OV_MAGIC);
}
// BEGIN duplication with vre
re = VRE_unpack(vre);
AN(re);
data = pcre2_match_data_create_from_pattern(re, NULL);
if (data == NULL) {
VRT_fail(ctx, "vmod_re: failed to create match data");
return 0;
}
// END duplication with vre
// BEGIN unneeded overhead (unless we get access to re_ctx also)
re_ctx = pcre2_match_context_create(NULL);
if (re_ctx == NULL) {
VRT_fail(ctx, "vmod_re: failed to create context");
goto out;
}
pcre2_set_depth_limit(re_ctx, vre_limits->depth);
pcre2_set_match_limit(re_ctx, vre_limits->match);
// END unneeded overhead
s = pcre2_match(re, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
0, data, re_ctx);
// XXX docs say "latest successful match", but we dont
task->len = 0;
s = VRE_capture(vre, subject, 0, 0,
ov->groups, MAX_MATCHES, vre_limits);
if (s <= PCRE2_ERROR_NOMATCH) {
if (s < PCRE2_ERROR_NOMATCH)
VSLb(ctx->vsl, SLT_VCL_Error,
"vmod re: regex match returned %d", s);
goto out;
return (0);
}
if (s > MAX_MATCHES) {
VSLb(ctx->vsl, SLT_VCL_Error,
......@@ -218,25 +195,10 @@ match(VRT_CTX, const vre_t *vre, VCL_STRING subject, struct vmod_priv *task,
MAX_MATCHES - 1);
s = MAX_MATCHES;
}
ovector = pcre2_get_ovector_pointer(data);
assert (s <= pcre2_get_ovector_count(data));
task->len = sizeof(*ov);
task->len = s;
ov->subject = subject;
for (i = 0; i < s * 2; i++)
ov->ovector[i] = ovector[i];
for ( ; i < MAX_OV; i++)
ov->ovector[i] = -1;
r = 1;
out: // XXX goto because this might be throw-away code
AN(data);
pcre2_match_data_free(data);
if (re_ctx != NULL)
pcre2_match_context_free(re_ctx);
return (r);
return (1);
}
static VCL_STRING
......@@ -244,8 +206,9 @@ backref(VRT_CTX, VCL_INT refnum, VCL_STRING fallback,
const struct vmod_priv *task)
{
ov_t *ov;
const char *substr, *start;
const char *substr;
int len;
txt m;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(fallback);
......@@ -262,30 +225,30 @@ backref(VRT_CTX, VCL_INT refnum, VCL_STRING fallback,
"vmod re: backref called without prior match");
return fallback;
}
if (task->len <= 0)
return fallback;
AN(WS_Allocated(ctx->ws, task->priv, sizeof(*ov)));
CAST_OBJ_NOTNULL(ov, task->priv, OV_MAGIC);
refnum *= 2;
assert(refnum + 1 < MAX_OV);
if (ov->ovector[refnum] == -1)
if (refnum >= task->len)
return fallback;
start = ov->subject + ov->ovector[refnum];
len = ov->ovector[refnum+1] - ov->ovector[refnum];
assert(len <= ov->ovector[1] - ov->ovector[0]);
if (start[len] == '\0')
substr = start;
else
substr = WS_Printf(ctx->ws, "%.*s", len, start);
m = ov->groups[refnum];
if (m.b == m.e)
return (fallback);
AN(m.b);
if (m.e[-1] == '\0')
return (m.b);
len = (int)(m.e - m.b);
substr = WS_Printf(ctx->ws, "%.*s", len, m.b);
if (substr == NULL) {
VSLb(ctx->vsl, SLT_VCL_Error,
"vmod re: insufficient workspace");
return fallback;
return (fallback);
}
return substr;
return (substr);
}
static inline const struct vre_limits *
......@@ -327,7 +290,6 @@ vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject,
}
AN(task);
task->len = 0;
return match(ctx, re->vre, subject, task,
get_limits(re, &buf, limit, limit_recursion));
......@@ -377,6 +339,7 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
limits.match = limit;
limits.depth = limit_recursion;
// XXX docs say "latest successful match", but we dont
task->len = 0;
vre = re_compile(pattern, 0, errbuf, sizeof errbuf, &erroffset);
if (vre == NULL) {
......
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