Commit 3df08fc5 authored by Geoff Simmons's avatar Geoff Simmons

return the fallback from backref() for missing matches, and add

more tests adapted from VMOD re
parent 33bba7d0
# looks like -*- vcl -*-
varnishtest "basic backrefs"
server s1 {
rxreq
txresp -hdr "Foo: barbaz" -hdr "Bar: bazquux" -hdr "Barf: barf" \
-body "1111\n"
} -start
varnish v1 -vcl+backend {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
sub vcl_init {
new barbaz = re2.regex("(bar)(baz)");
new bazplus = re2.regex("(baz)(.+)");
new fourdots = re2.regex("(.)(.)(.)(.)");
}
sub vcl_backend_response {
if (barbaz.match(beresp.http.foo)) {
set beresp.http.foo0 = barbaz.backref(0, "error0");
set beresp.http.foo1 = barbaz.backref(1, "error1");
set beresp.http.foo2 = barbaz.backref(2, "error2");
} else {
set beresp.status = 999;
}
if (bazplus.match(beresp.http.bar)) {
set beresp.http.bar0 = bazplus.backref(0, "error0");
set beresp.http.bar1 = bazplus.backref(1, "error1");
set beresp.http.bar2 = bazplus.backref(2, "error2");
} else {
set beresp.status = 999;
}
if (barbaz.match(beresp.http.foo)
&& bazplus.match(beresp.http.bar)) {
set beresp.http.foo20 = barbaz.backref(0, "error0");
set beresp.http.foo21 = barbaz.backref(1, "error1");
set beresp.http.foo22 = barbaz.backref(2, "error2");
set beresp.http.bar20 = bazplus.backref(0, "error0");
set beresp.http.bar21 = bazplus.backref(1, "error1");
set beresp.http.bar22 = bazplus.backref(2, "error2");
} else {
set beresp.status = 999;
}
if (fourdots.match(beresp.http.barf)) {
set beresp.http.frap
= "_" + fourdots.backref(0, "error0") + "_"
+ fourdots.backref(4, "error4")
+ fourdots.backref(3, "error3")
+ fourdots.backref(2, "error2") + "p_";
} else {
set beresp.status = 999;
}
}
} -start
client c1 {
txreq
rxresp
expect resp.http.foo0 == "barbaz"
expect resp.http.foo1 == "bar"
expect resp.http.foo2 == "baz"
expect resp.http.bar0 == "bazquux"
expect resp.http.bar1 == "baz"
expect resp.http.bar2 == "quux"
expect resp.http.foo20 == "barbaz"
expect resp.http.foo21 == "bar"
expect resp.http.foo22 == "baz"
expect resp.http.bar20 == "bazquux"
expect resp.http.bar21 == "baz"
expect resp.http.bar22 == "quux"
expect resp.http.frap == "_barf_frap_"
} -run
# looks like -*- vcl -*-
varnishtest "backref failure"
server s1 {
rxreq
txresp -hdr "Foo: barbaz" -hdr "Bar: bazquux" -hdr "Barf: barf" \
-body "1111\n"
} -start
varnish v1 -vcl+backend {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
sub vcl_init {
new frobnitz = re2.regex("(frob)(nitz)");
new barbaz = re2.regex("(bar)(baz)");
new azbc = re2.regex("(a|(z))(bc)");
}
sub vcl_deliver {
# Call to backref() before match()
set resp.http.nomatch = barbaz.backref(0, "fallback");
/* does not match */
if (frobnitz.match(resp.http.foo)) {
set resp.http.frob = "nitz";
}
/* ... so all backrefs fail */
set resp.http.frob0 = frobnitz.backref(0, "fallback0");
set resp.http.frob1 = frobnitz.backref(1, "fallback1");
set resp.http.frob2 = frobnitz.backref(2, "fallback2");
set resp.http.frob3 = frobnitz.backref(3, "fallback3");
/* matches with backrefs, as above */
if (barbaz.match(resp.http.foo)) {
set resp.http.foo0 = barbaz.backref(0, "error0");
set resp.http.foo1 = barbaz.backref(1, "error1");
set resp.http.foo2 = barbaz.backref(2, "error2");
}
/* does not match */
if (barbaz.match(resp.http.barf)) {
set resp.http.puke = "match";
}
/* ... so all backrefs fail, including the backrefs
* from the previous match
*/
set resp.http.barf0 = barbaz.backref(0, "fallback0");
set resp.http.barf1 = barbaz.backref(1, "fallback1");
set resp.http.barf2 = barbaz.backref(2, "fallback2");
if (azbc.match("abc")) {
set resp.http.abc1 = azbc.backref(1, "error1");
set resp.http.abc2 = azbc.backref(2, "none");
set resp.http.abc3 = azbc.backref(3, "error3");
} else {
set resp.http.abc = "fail";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.nomatch == "fallback"
expect resp.http.frob == <undef>
expect resp.http.frob0 == "fallback0"
expect resp.http.frob1 == "fallback1"
expect resp.http.frob2 == "fallback2"
expect resp.http.foo0 == "barbaz"
expect resp.http.foo1 == "bar"
expect resp.http.foo2 == "baz"
expect resp.http.puke == <undef>
expect resp.http.barf0 == "fallback0"
expect resp.http.barf1 == "fallback1"
expect resp.http.barf2 == "fallback2"
expect resp.http.abc == <undef>
expect resp.http.abc1 == "a"
expect resp.http.abc2 == "none"
expect resp.http.abc3 == "bc"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
# due to calling barbaz.backref() before .match()
expect * = VCL_Error "^vmod re2 error: barbaz\.backref\(0, \"fallback\"\): backref called without prior match$"
# get the "out of range" error message even when the backref
# would have also failed due to failing prior match
expect * = VCL_Error "^vmod re2 error: frobnitz\.backref\(3, \"fallback3\"\): backref out of range \(max 3\)$"
expect * = End
} -run
# looks like -*- vcl -*-
varnishtest "non-capturing parentheses"
server s1 {
rxreq
txresp -hdr "Foo: barbaz" -body "1111\n"
} -start
varnish v1 -vcl+backend {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
sub vcl_init {
new barbaz = re2.regex("(?:bar)(baz)");
}
sub vcl_backend_response {
if (barbaz.match(beresp.http.foo)) {
set beresp.http.foo0 = barbaz.backref(0, "error0");
set beresp.http.foo1 = barbaz.backref(1, "error1");
set beresp.http.foo2 = barbaz.backref(2, "fallback");
} else {
set beresp.status = 999;
}
}
} -start
client c1 {
txreq
rxresp
expect resp.http.foo0 == "barbaz"
expect resp.http.foo1 == "baz"
expect resp.http.foo2 == "fallback"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
# due to calling barbaz.backref() before .match()
expect * = VCL_Error "^vmod re2 error: barbaz\.backref\(2, \"fallback\"\): backref out of range \(max 1\)$"
expect * = End
} -run
# looks like -*- vcl -*-
varnishtest "backref limits"
server s1 {
rxreq
txresp -hdr "Foo: 123456789012" -body "1111\n"
} -start
varnish v1 -vcl+backend {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
sub vcl_init {
new elevendots = re2.regex("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
new twentydots
= re2.regex("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
}
sub vcl_backend_response {
if (elevendots.match(beresp.http.foo)) {
set beresp.http.foo0 = elevendots.backref(0, "error0");
set beresp.http.foo1 = elevendots.backref(1, "error1");
set beresp.http.foo2 = elevendots.backref(2, "error2");
set beresp.http.foo3 = elevendots.backref(3, "error3");
set beresp.http.foo4 = elevendots.backref(4, "error4");
set beresp.http.foo5 = elevendots.backref(5, "error5");
set beresp.http.foo6 = elevendots.backref(6, "error6");
set beresp.http.foo7 = elevendots.backref(7, "error7");
set beresp.http.foo8 = elevendots.backref(8, "error8");
set beresp.http.foo9 = elevendots.backref(9, "error9");
set beresp.http.foo10
= elevendots.backref(10, "error10");
set beresp.http.foo11
= elevendots.backref(11, "error11");
set beresp.http.foo12
= elevendots.backref(12, "fallback");
} else {
set beresp.status = 999;
}
}
sub vcl_deliver {
if (twentydots.match("123456789012345678901")) {
set resp.http.bar0 = twentydots.backref(0, "error0");
set resp.http.bar1 = twentydots.backref(1, "error1");
set resp.http.bar2 = twentydots.backref(2, "error2");
set resp.http.bar3 = twentydots.backref(3, "error3");
set resp.http.bar4 = twentydots.backref(4, "error4");
set resp.http.bar5 = twentydots.backref(5, "error5");
set resp.http.bar6 = twentydots.backref(6, "error6");
set resp.http.bar7 = twentydots.backref(7, "error7");
set resp.http.bar8 = twentydots.backref(8, "error8");
set resp.http.bar9 = twentydots.backref(9, "error9");
set resp.http.bar10 = twentydots.backref(10, "error10");
set resp.http.bar11 = twentydots.backref(11, "error11");
set resp.http.bar12 = twentydots.backref(12, "error12");
set resp.http.bar13 = twentydots.backref(13, "error13");
set resp.http.bar14 = twentydots.backref(14, "error14");
set resp.http.bar15 = twentydots.backref(15, "error15");
set resp.http.bar16 = twentydots.backref(16, "error16");
set resp.http.bar17 = twentydots.backref(17, "error17");
set resp.http.bar18 = twentydots.backref(18, "error18");
set resp.http.bar19 = twentydots.backref(19, "error19");
set resp.http.bar20 = twentydots.backref(20, "error20");
set resp.http.bar21 = twentydots.backref(21, "error21");
} else {
set resp.status = 999;
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.foo0 == "12345678901"
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 == "1"
expect resp.http.foo12 == "fallback"
expect resp.http.bar0 == "12345678901234567890"
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 == "1"
expect resp.http.bar12 == "2"
expect resp.http.bar13 == "3"
expect resp.http.bar14 == "4"
expect resp.http.bar15 == "5"
expect resp.http.bar16 == "6"
expect resp.http.bar17 == "7"
expect resp.http.bar18 == "8"
expect resp.http.bar19 == "9"
expect resp.http.bar20 == "0"
expect resp.http.bar21 == "error21"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: elevendots\.backref\(12, \"fallback\"\): backref out of range \(max 11\)$"
expect * = End
expect * * Begin req
expect * = VCL_Error "^vmod re2 error: twentydots\.backref\(21, \"error21\"\): backref out of range \(max 20\)$"
expect * = End
} -run
# looks like -*- vcl -*-
varnishtest "re2.backref not affected by standard VCL regex code"
server s1 {
rxreq
txresp -hdr "Foo: barbaz" -body "1111\n"
} -start
varnish v1 -vcl+backend {
import re2 from "${vmod_topbuild}/src/.libs/libvmod_re2.so";
sub vcl_init {
new barbaz = re2.regex("(bar)baz");
}
sub vcl_backend_response {
if (!barbaz.match(beresp.http.foo)) {
set beresp.status = 999;
}
if (beresp.http.foo ~ "bar(baz)") {
set beresp.http.tilde0 = barbaz.backref(0, "tilde0");
set beresp.http.tilde1 = barbaz.backref(1, "tilde1");
} else {
set beresp.status = 999;
}
if (beresp.http.foo !~ "bar(quux)") {
set beresp.http.neg0 = barbaz.backref(0, "neg0");
set beresp.http.neg1 = barbaz.backref(1, "neg1");
} else {
set beresp.status = 999;
}
set beresp.http.regsub
= regsub(beresp.http.foo, "bar(baz)", "\1");
set beresp.http.regsub0 = barbaz.backref(0, "regsub0");
set beresp.http.regsub1 = barbaz.backref(1, "regsub1");
set beresp.http.regsuball
= regsuball(beresp.http.foo, "(.)", "x");
set beresp.http.regsuball0 = barbaz.backref(0, "regsuball0");
set beresp.http.regsuball1 = barbaz.backref(1, "regsuball1");
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.tilde0 == "barbaz"
expect resp.http.tilde1 == "bar"
expect resp.http.neg0 == "barbaz"
expect resp.http.neg1 == "bar"
expect resp.http.regsub == "baz"
expect resp.http.regsub0 == "barbaz"
expect resp.http.regsub1 == "bar"
expect resp.http.regsuball == "xxxxxx"
expect resp.http.regsuball0 == "barbaz"
expect resp.http.regsuball1 == "bar"
} -run
......@@ -224,7 +224,10 @@ vmod_regex_backref(VRT_CTX, struct vmod_re2_regex *re, VCL_INT refnum,
re->vcl_name, refnum, fallback, err);
return fallback;
}
assert(len >= 0);
if (capture == NULL)
return fallback;
if (len == 0)
return "";
if ((backref = WS_Copy(ctx->ws, capture, len + 1)) == 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