Commit c70e410a authored by Geoff Simmons's avatar Geoff Simmons

Breaking changes to invoke VCL failure for "can't happen" errors.

Up to now we have emitted sentinel values for this class of errors,
a relic of the time before VCL failure was introduced, when the VMOD
was first developed. This may lead to fatal errors going unnoticed.
These are the sorts of errors that should fail fast in development
and testing, and never make it into production.

We were already using VCL failure for the integer() method, since
there is no sentinel integer.

VCL failure is now invoked for these errors:

- any regex compilation failure

- all out of workspace errors

- compile() or add() called in any VCL subroutine besides vcl_init

- match() called for a set that was not compiled

- failures reported by the RE2 lib for: match(), backref(),
  namedref(), the rewrite operations (sub, suball and extract),
  cost(), quotemeta()

- numeric index reference for a set object (n parameter) that is out
  of range (greater than the number of patterns in the set)

- functions and methods that require a previous successful match
  operation (with information stored in priv_task) when there was no
  prior match, or the previous macth failed.

- use of select=UNIQUE when more than one pattern in a set matched

- numeric (by index) or "associative" (after match) retrieval of an
  object for a set when no such object was saved in the constructor:
  strings, backends, regexen, etc

- any of the following are undefined (NULL): fallbacks; patterns for
  regex functions (which are compiled at runtime); the text and
  rewrite parameters for the rewrite operations; name parameter
  for namedrefs

- also if the named parameter for namedrefs is the empty string

- backref number out of range (greater than the number of backrefs)

- backref or namedref attempted without a prior match

- backref or namedref when never_capture=true in the contructor

- low-level failures reported by RE2 (eg cannot determine the number
  of backref groups). Most of these are possible, since the call
  returns an error status, but I have never seen them happen.

VTC tests have been revised for the new error handling, which changes
quite a bit in this commit.

While we're here, use backend None in the tests where appropriate.
Note that "bad_ip" backends are still necessary to test methods and
functions that retrieve backends (numeric or associative references
for sets).

Error reporting is now done with VCL_fail(), so we get rid of the
errmsg() function, and with it the re2.c source (since that was all
there was in re2.c).
parent 07cbe881
......@@ -1638,12 +1638,7 @@ Example:
black.hdr_filter(resp, false);
}
#### STRING quotemeta(STRING, STRING fallback)
STRING quotemeta(
STRING,
STRING fallback="**QUOTEMETA FUNCTION FAILED**"
)
#### STRING quotemeta(STRING)
Returns a copy of the argument string with all regex metacharacters
escaped via backslash. When the returned string is used as a regular
......
......@@ -10,7 +10,6 @@ libvmod_re2_la_SOURCES = \
vmod_re2.h \
vmod_re2.c \
set.c \
re2.c \
vre2/vre2.h \
vre2/vre2.cpp \
vre2/vre2set.h \
......@@ -25,7 +24,7 @@ MAINTAINERCLEANFILES = $(dist_man_MANS)
libvmod_re2_la_LIBADD = @RE2_LIBS@
vmod_re2.c set.c re2.c: vmod_re2.h
vmod_re2.c set.c: vmod_re2.h
vmod_re2.h: vcc_if.h
......
/*-
* Copyright (c) 2017 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "vmod_re2.h"
void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
AZ(ctx->method & VCL_MET_TASK_H);
va_start(args, fmt);
if (ctx->vsl)
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
else
VSLv(SLT_VCL_Error, 0, fmt, args);
va_end(args);
}
This diff is collapsed.
......@@ -23,7 +23,7 @@ varnish v1 -cli "vcl.list"
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......
This diff is collapsed.
......@@ -4,7 +4,8 @@ varnishtest "backref limits"
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
import std;
backend b None;
sub vcl_init {
new elevendots = re2.regex("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
......@@ -32,11 +33,13 @@ varnish v1 -vcl {
= elevendots.backref(10, "error10");
set resp.http.foo11
= elevendots.backref(11, "error11");
set resp.http.foo12
= elevendots.backref(12, "fallback");
} else {
set resp.status = 999;
}
if (req.http.Int11) {
set resp.http.Backref11
= elevendots.backref(std.integer(req.http.Int11));
}
if (twentydots.match("123456789012345678901")) {
set resp.http.bar0 = twentydots.backref(0, "error0");
......@@ -60,10 +63,13 @@ varnish v1 -vcl {
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;
}
if (req.http.Int20) {
set resp.http.Backref20
= twentydots.backref(std.integer(req.http.Int20));
}
}
} -start
......@@ -84,7 +90,6 @@ client c1 {
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"
......@@ -106,19 +111,40 @@ client c1 {
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" {
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod re2 failure: elevendots\.backref\(ref=12, fallback="[^"]+"\): backref out of range \(max 11\)$}
# "
expect 0 = RespHeader {^Backref11: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: elevendots.backref.ref=12, fallback=.fallback..: backref out of range .max 11.$"
expect * = VCL_Error "^vmod re2 error: twentydots.backref.ref=21, fallback=.error21..: backref out of range .max 20.$"
expect * = VCL_Error {^vmod re2 failure: twentydots\.backref\(ref=21, fallback="[^"]+"\): backref out of range \(max 20\)$}
# "
expect 0 = RespHeader {^Backref20: $}
expect 0 = VCL_return fail
expect * = End
} -start
client c2 {
txreq -hdr "Int11: 12"
expect_close
} -run
client c3 {
txreq -hdr "Int20: 21"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
import std;
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -139,10 +165,13 @@ varnish v1 -vcl {
set resp.http.foo9 = re2.backref(9, "error9");
set resp.http.foo10 = re2.backref(10, "error10");
set resp.http.foo11 = re2.backref(11, "error11");
set resp.http.foo12 = re2.backref(12, "fallback");
} else {
set resp.status = 999;
}
if (req.http.Int11) {
set resp.http.Backref11
= re2.backref(std.integer(req.http.Int11));
}
if (re2.match("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)",
"123456789012345678901")) {
......@@ -167,21 +196,37 @@ varnish v1 -vcl {
set resp.http.bar18 = re2.backref(18, "error18");
set resp.http.bar19 = re2.backref(19, "error19");
set resp.http.bar20 = re2.backref(20, "error20");
set resp.http.bar21 = re2.backref(21, "error21");
} else {
set resp.status = 999;
}
if (req.http.Int20) {
set resp.http.Backref20
= re2.backref(std.integer(req.http.Int20));
}
}
}
logexpect l2 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * * Begin req
expect * = VCL_Error "^vmod re2 error: re2.backref.ref=12, fallback=.fallback..: backref out of range .max 11.$"
expect * = VCL_Error "^vmod re2 error: re2.backref.ref=21, fallback=.error21..: backref out of range .max 20.$"
client c1 -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod re2 failure: re2\.backref\(ref=12, fallback="[^"]+"\): backref out of range \(max 11\)$}
# "
expect 0 = RespHeader {^Backref11: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod re2 failure: re2\.backref\(ref=21, fallback="[^"]+"\): backref out of range \(max 20\)$}
# "
expect 0 = RespHeader {^Backref20: $}
expect 0 = VCL_return fail
expect * = End
} -start
client c1 -run
client c2 -run
client c3 -run
logexpect l2 -wait
logexpect l1 -wait
......@@ -6,7 +6,7 @@ varnishtest "cached compiled regexen"
varnish v1 -vcl+backend {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new barbaz = re2.regex("(bar)(baz)");
......
This diff is collapsed.
......@@ -4,7 +4,7 @@ varnishtest "cost() function"
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
# Tests from re2 testing/re2_test.cc
......@@ -26,7 +26,9 @@ varnish v1 -vcl {
set resp.http.C-Medium-F = re2.cost("medium.*regexp");
set resp.http.C-Complex-F = re2.cost("complex.{1,128}regexp");
set resp.http.Fail-F = re2.cost("(");
if (req.http.Fail) {
set resp.http.Fail-F = re2.cost("(");
}
}
} -start
......@@ -43,11 +45,17 @@ client c1 {
expect resp.http.C-Simple-F == resp.http.C-Simple
expect resp.http.C-Medium-F == resp.http.C-Medium
expect resp.http.C-Complex-F == resp.http.C-Complex
expect resp.http.Fail-F == "-1"
} -run
client c1 {
txreq -hdr "Fail: oops"
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod re2 error: re2\.cost\("\("\): Cannot compile: }
expect * = VCL_Error {^vmod re2 failure: re2\.cost\("\("\): Cannot compile: }
expect 0 = RespHeader {^Fail-F: -1$}
expect 0 = VCL_return fail
expect * = End
} -run
......@@ -8,7 +8,7 @@ varnishtest "latin1 and utf8 encoding"
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new ninebytes = re2.regex("^.........$");
......@@ -125,7 +125,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new ninebytes = re2.set();
......@@ -195,7 +195,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -242,7 +242,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -289,7 +289,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......
......@@ -2,20 +2,20 @@
varnishtest "extract() method and function"
varnish v1 -vcl {
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import ${vmod_re2};
backend be { .host = "${bad_ip}"; }
sub vcl_init {
new email = re2.regex("(.*)@([^.]*)");
new dotstar = re2.regex(".*");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
sub vcl_deliver {
# Tests from re2 testing/re2_test.cc
set resp.http.uucp = email.extract("boris@kremvax.ru", "\2!\1");
set resp.http.quote = dotstar.extract("foo", "'\0'");
......@@ -29,38 +29,60 @@ varnish v1 -vcl {
"fallbackf");
# Undefined fallback
set resp.http.undeffallback
= email.extract("foo", "bar", req.http.undef);
set resp.http.undeffallbackf
= re2.extract(".", "foo", "bar", req.http.undef);
if (req.http.Test == "fallbackundef") {
if (req.http.Call == "method") {
set resp.http.undeffallback
= email.extract("foo", "bar",
req.http.undef);
}
else {
set resp.http.undeffallback
= re2.extract(".", "foo", "bar",
req.http.undef);
}
}
# Undefined pattern in the function
set resp.http.undefpattern
= re2.extract(req.http.undef, "", "", "pattern undef");
if (req.http.Test == "patternundef") {
set resp.http.undefpattern
= re2.extract(req.http.undef, "", "");
}
# Undefined text
set resp.http.undeftext
= email.extract(req.http.undef, "x", "text undef");
set resp.http.undeftextf
= re2.extract(".", req.http.undef, "x", "text undef");
if (req.http.Test == "textundef") {
if (req.http.Call == "method") {
set resp.http.undeftext
= email.extract(req.http.undef, "x");
}
else {
set resp.http.undeftext
= re2.extract(".", req.http.undef, "x");
}
}
# Undefined rewrite
set resp.http.undefrewrite
= email.extract("b", req.http.undef, "rewrite undef");
set resp.http.undefrewritef
= re2.extract(".", "b", req.http.undef,"rewrite undef");
if (req.http.Test == "rewriteundef") {
if (req.http.Call == "method") {
set resp.http.undefrewrite
= email.extract("b", req.http.undef);
}
else {
set resp.http.undefrewrite
= re2.extract(".", "b", req.http.undef);
}
}
# Default fallbacks
set resp.http.fallback = email.extract("foo", "bar");
set resp.http.fallbackf = re2.extract("(.*)@([^.]*)", "foo",
"bar");
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.uucp == "kremvax!boris"
expect resp.http.quote == "'foo'"
expect resp.http.uucpf == "kremvax!boris"
......@@ -69,33 +91,131 @@ client c1 {
expect resp.http.fail == "fallback"
expect resp.http.failf == "fallbackf"
expect resp.http.undeffallback == "**EXTRACT METHOD FAILED**"
expect resp.http.undeffallbackf == "**EXTRACT FUNCTION FAILED**"
expect resp.http.fallback == "**EXTRACT METHOD FAILED**"
expect resp.http.fallbackf == "**EXTRACT FUNCTION FAILED**"
} -run
expect resp.http.undefpattern == "pattern undef"
client c1 {
txreq -hdr "Test: fallbackundef" -hdr "Call: method"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undeffallback == <undef>
expect_close
} -run
expect resp.http.undeftext == "text undef"
expect resp.http.undeftextf == "text undef"
client c1 {
txreq -hdr "Test: fallbackundef" -hdr "Call: function"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undeffallback == <undef>
expect_close
} -run
expect resp.http.undefrewrite == "rewrite undef"
expect resp.http.undefrewritef == "rewrite undef"
client c1 {
txreq -hdr "Test: patternundef"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undefpattern == <undef>
expect_close
} -run
expect resp.http.fallback == "**EXTRACT METHOD FAILED**"
expect resp.http.fallbackf == "**EXTRACT FUNCTION FAILED**"
client c1 {
txreq -hdr "Test: textundef" -hdr "Call: method"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undeftext == <undef>
expect_close
} -run
client c1 {
txreq -hdr "Test: textundef" -hdr "Call: function"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undeftext == <undef>
expect_close
} -run
client c1 {
txreq -hdr "Test: rewriteundef" -hdr "Call: method"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undefrewrite == <undef>
expect_close
} -run
client c1 {
txreq -hdr "Test: rewriteundef" -hdr "Call: function"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
expect resp.http.undefrewrite == <undef>
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = ReqHeader {^Test: fallbackundef$}
expect * = ReqHeader {^Call: method$}
expect * = VCL_Error {^vmod re2 failure: email\.extract\(\): fallback is undefined$}
expect 0 = RespHeader {^undeffallback: $}
expect 0 = VCL_return fail
expect * = End
expect * = VCL_Error "^vmod re2 error: email.extract..: fallback is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.extract..: fallback is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.extract.pattern=<undefined>, fallback=.pattern undef..: pattern is undefined$"
expect 0 * Begin req
expect * = ReqHeader {^Test: fallbackundef$}
expect * = ReqHeader {^Call: function$}
expect * = VCL_Error {^vmod re2 failure: re2\.extract\(\): fallback is undefined$}
expect 0 = RespHeader {^undeffallback: $}
expect 0 = VCL_return fail
expect * = End
expect * = VCL_Error "^vmod re2 error: email.extract.text=<undefined>, fallback=.text undef..: text is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.extract.pattern=..., text=<undefined>, fallback=.text undef..: text is undefined$"
expect 0 * Begin req
expect * = ReqHeader {^Test: patternundef$}
expect * = VCL_Error {^vmod re2 failure: re2\.extract\(pattern=<undefined>, fallback="[^"]+"\): pattern is undefined$}
# "
expect 0 = RespHeader {^undefpattern: $}
expect 0 = VCL_return fail
expect * = End
expect * = VCL_Error "^vmod re2 error: email.extract.text=.b., rewrite=<undefined>, fallback=.rewrite undef..: rewrite is undefined$"
expect * = VCL_Error "^vmod re2 error: re2.extract.pattern=..., text=.b., rewrite=<undefined>, fallback=.rewrite undef..: rewrite is undefined$"
expect 0 * Begin req
expect * = ReqHeader {^Test: textundef$}
expect * = ReqHeader {^Call: method$}
expect * = VCL_Error {^vmod re2 failure: email\.extract\(text=<undefined>, fallback="[^"]+"\): text is undefined$}
# "
expect 0 = RespHeader {^undeftext: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = ReqHeader {^Test: textundef$}
expect * = ReqHeader {^Call: function$}
expect * = VCL_Error {^vmod re2 failure: re2\.extract\(pattern="\.", text=<undefined>, fallback="[^"]+"\): text is undefined$}
# "
expect 0 = RespHeader {^undeftext: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = ReqHeader {^Test: rewriteundef$}
expect * = ReqHeader {^Call: method$}
expect * = VCL_Error {^vmod re2 failure: email\.extract\(text="b", rewrite=<undefined>, fallback="[^"]+"\): rewrite is undefined$}
# "
expect 0 = RespHeader {^undefrewrite: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = ReqHeader {^Test: rewriteundef$}
expect * = ReqHeader {^Call: function$}
expect * = VCL_Error {^vmod re2 failure: re2\.extract\(pattern="\.", text="b", rewrite=<undefined>, fallback="[^"]+"\): rewrite is undefined$}
# "
expect 0 = RespHeader {^undefrewrite: $}
expect 0 = VCL_return fail
expect * = End
} -run
......@@ -4,7 +4,7 @@ varnishtest "set.hdr_filter()"
varnish v1 -vcl {
import ${vmod_re2};
backend be { .host = "${bad_ip}"; }
backend be None;
sub vcl_init {
new white = re2.set(anchor=start);
......
......@@ -6,7 +6,7 @@ varnish v1 -vcl {
import ${vmod_re2};
import std;
backend be { .host = "${bad_ip}"; }
backend be None;
sub vcl_init {
# \b is insufficient for the ,<remove> case:
......
......@@ -72,7 +72,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -87,13 +87,11 @@ varnish v1 -vcl {
client c2 {
txreq
rxresp
expect resp.status == "200"
expect resp.http.undef == <undef>
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: re2.match.pattern=.<undefined>., text=...: pattern is undefined$"
expect * = VCL_Error "^vmod re2 failure: re2.match.pattern=.<undefined>., text=...: pattern is undefined$"
expect * = End
} -run
This diff is collapsed.
This diff is collapsed.
......@@ -2,30 +2,39 @@
varnishtest "non-capturing parentheses"
server s1 {
server s1 -repeat 3 {
rxreq
txresp -hdr "Foo: barbaz" -body "1111\n"
} -start
varnish v1 -vcl+backend {
import ${vmod_re2};
import std;
sub vcl_init {
new barbaz = re2.regex("(?:bar)(baz)");
}
sub vcl_recv {
return (pass);
}
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");
set beresp.http.foo0 = barbaz.backref(0);
set beresp.http.foo1 = barbaz.backref(1);
if (bereq.http.Test == "method") {
set beresp.http.foo2 = barbaz.backref(2);
}
} else {
set beresp.status = 999;
}
if (re2.match("(?:bar)(baz)", beresp.http.foo)) {
set beresp.http.foo0f = re2.backref(0, "error0");
set beresp.http.foo1f = re2.backref(1, "error1");
set beresp.http.foo2f = re2.backref(2, "fallback");
set beresp.http.foo0f = re2.backref(0);
set beresp.http.foo1f = re2.backref(1);
if (bereq.http.Test == "function") {
set beresp.http.foo2f = re2.backref(2);
}
} else {
set beresp.status = 999;
}
......@@ -47,12 +56,11 @@ varnish v1 -vcl+backend {
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.foo0 == "barbaz"
expect resp.http.foo1 == "baz"
expect resp.http.foo2 == "fallback"
expect resp.http.foo0f == "barbaz"
expect resp.http.foo1f == "baz"
expect resp.http.foo2f == "fallback"
expect resp.http.sub == "barbazbaz"
expect resp.http.subf == "barbazbaz"
expect resp.http.suball == "barbazbaz"
......@@ -61,9 +69,38 @@ client c1 {
expect resp.http.extractf == "barbazbaz"
} -run
client c1 {
txreq -hdr "Test: method"
rxresp
expect resp.status == 503
expect resp.reason == "Service Unavailable"
expect resp.http.foo2 == <undef>
expect_close
} -run
client c1 {
txreq -hdr "Test: function"
rxresp
expect resp.status == 503
expect resp.reason == "Service Unavailable"
expect resp.http.foo2f == <undef>
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: barbaz.backref.ref=2, fallback=.fallback..: backref out of range .max 1.$"
expect * = VCL_Error "^vmod re2 error: re2.backref.ref=2, fallback=.fallback..: backref out of range .max 1.$"
expect 0 * Begin bereq
expect * = BereqHeader {^Test: method$}
expect * = VCL_Error {^vmod re2 failure: barbaz\.backref\(ref=2, fallback="[^"]+"\): backref out of range \(max 1\)$}
# "
expect 0 = BerespHeader {^foo2: $}
expect 0 = VCL_return fail
expect * = End
expect 0 * Begin bereq
expect * = BereqHeader {^Test: function$}
expect * = VCL_Error {^vmod re2 failure: re2\.backref\(ref=2, fallback="[^"]+"\): backref out of range \(max 1\)$}
# "
expect 0 = BerespHeader {^foo2f: $}
expect 0 = VCL_return fail
expect * = End
} -run
......@@ -8,7 +8,7 @@ varnishtest "options: literal never_nl dot_nl case_sensitive one_line longest_ma
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new literal = re2.regex("(|)^$.[*+?]{5,10},\\", literal=true);
......@@ -126,7 +126,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -209,7 +209,7 @@ client c1 -run
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new literal = re2.set(literal=true);
......@@ -345,7 +345,7 @@ client c2 {
varnish v1 -vcl {
import ${vmod_re2};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_recv {
return(synth(200));
......@@ -436,7 +436,7 @@ client c2 {
varnish v1 -vcl {
import ${vmod_re2};