Commit 7e9b3177 authored by Nils Goroll's avatar Nils Goroll

pull vre_limits into the vmod

We cannot access the varnishd params from a $ABI vrt vmod any more
and doing so does not appear a strong enough reason to change the $ABI.

Previously, pcre limits were taken from the varnish parameters
pcre_match_limit and pcre_match_limit_recursion, now they can be
defined on the re object or match level.
parent 55a9527b
Pipeline #422 skipped
......@@ -106,8 +106,8 @@ never changes during the lifetime of VCL, use ``match``.
CONTENTS
========
* regex(STRING)
* BOOL match_dyn(STRING, STRING)
* regex(STRING, INT, INT)
* BOOL match_dyn(STRING, STRING, INT, INT)
* STRING backref_dyn(INT, STRING)
* STRING version()
......@@ -118,7 +118,7 @@ regex
::
new OBJ = regex(STRING)
new OBJ = regex(STRING, INT limit=1000, INT limit_recursion=1000)
Description
Create a regex object with the given regular expression. The
......@@ -129,6 +129,10 @@ Description
If the regular expression fails to compile, then the VCL
load fails with an error message describing the problem.
The optional parameters ``limit`` and ``limit_recursion`` are
per-object defaults for the respective parameters of the
`func_regex.match`_ and `func_match_dyn`_ mehods.
Example
``new myregex = re.regex("\bmax-age\s*=\s*(\d+)");``
......@@ -139,13 +143,27 @@ regex.match
::
BOOL regex.match(STRING)
BOOL regex.match(STRING, INT limit=0, INT limit_recursion=0)
Description
Determines whether the given string matches the regex compiled
by the constructor; functionally equivalent to VCL's infix
operator ``~``.
The optional parameter ``limit`` restricts the number of
internal matching function calls in a ``pcre_exec()``
execution, analoguous to the varnishd
``pcre_match_limit`` parameter. For the default
value 0, the ``limit`` given to the constructor `obj_regex`_
is used.
The optional parameter ``limit_recursion`` restricts the
number of internal matching function recursions in a
``pcre_exec()`` execution, analoguous to the varnishd
``pcre_match_limit_recursion`` parameter. For the default
value 0, the ``limit_recursion`` given to the constructor
`obj_regex`_ is used.
Example
``if (myregex.match(beresp.http.Surrogate-Control)) { # ...``
......@@ -189,7 +207,7 @@ match_dyn
::
BOOL match_dyn(STRING, STRING)
BOOL match_dyn(STRING, STRING, INT limit=1000, INT limit_recursion=1000)
Description
Compiles the regular expression given in the first argument,
......@@ -201,6 +219,10 @@ Description
with the tag ``VCL_Error``, and ``match_dyn`` returns
``false``.
For parameters ``limit`` and ``limit_recursion`` see
`func_regex.match`_, except that there is no object to inherit
defaults from.
Example
``if (re.match_dyn(req.http.Foo + "(\d+)", beresp.http.Bar)) { # ...``
......
varnishtest "regex compilation failure"
varnishtest "regex constructor errors"
varnish v1 -vcl { backend b { .host = "${bad_ip}"; } } -start
......@@ -10,3 +10,21 @@ varnish v1 -errvcl {vmod re: error compiling regex} {
new paren = re.regex("(");
}
}
varnish v1 -errvcl {vmod re: invalid limit 0 in bad constructor} {
import re from "${vmod_topbuild}/src/.libs/libvmod_re.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new bad = re.regex(".", limit=0);
}
}
varnish v1 -errvcl {vmod re: invalid limit_recursion 0 in bad constructor} {
import re from "${vmod_topbuild}/src/.libs/libvmod_re.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new bad = re.regex(".", limit_recursion=0);
}
}
......@@ -61,6 +61,7 @@ struct vmod_re_regex {
unsigned magic;
#define VMOD_RE_REGEX_MAGIC 0x955706ee
vre_t *vre;
struct vre_limits vre_limits;
};
typedef struct ov_s {
......@@ -93,7 +94,7 @@ errmsg(VRT_CTX, const char *fmt, ...)
VCL_VOID
vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name,
VCL_STRING pattern)
VCL_STRING pattern, VCL_INT limit, VCL_INT limit_recursion)
{
struct vmod_re_regex *re;
vre_t *vre;
......@@ -106,15 +107,31 @@ vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name,
AN(vcl_name);
AN(pattern);
if ((vre = VRE_compile(pattern, 0, &error, &erroffset)) == NULL)
if (limit < 1) {
errmsg(ctx, "vmod re: invalid limit %d in %s constructor",
limit, vcl_name);
return;
}
if (limit_recursion < 1) {
errmsg(ctx, "vmod re: invalid limit_recursion %d "
"in %s constructor", limit_recursion, vcl_name);
return;
}
if ((vre = VRE_compile(pattern, 0, &error, &erroffset)) == NULL) {
errmsg(ctx, "vmod re: error compiling regex \"%s\" in %s "
"constructor: %s (at offset %d)", pattern, vcl_name,
error, erroffset);
return;
}
ALLOC_OBJ(re, VMOD_RE_REGEX_MAGIC);
AN(re);
*rep = re;
re->vre = vre;
re->vre_limits.match = limit;
re->vre_limits.match_recursion = limit_recursion;
*rep = re;
}
VCL_VOID
......@@ -133,7 +150,8 @@ vmod_regex__fini(struct vmod_re_regex **rep)
}
static VCL_BOOL
match(VRT_CTX, vre_t *vre, VCL_STRING subject, struct vmod_priv *task)
match(VRT_CTX, vre_t *vre, VCL_STRING subject, struct vmod_priv *task,
const struct vre_limits *vre_limits)
{
ov_t *ov;
int s, nov[MAX_OV];
......@@ -160,8 +178,7 @@ match(VRT_CTX, vre_t *vre, VCL_STRING subject, struct vmod_priv *task)
}
len = strlen(subject);
s = VRE_exec(vre, subject, len, 0, 0, nov, MAX_OV,
vparam_vre_limits);
s = VRE_exec(vre, subject, len, 0, 0, nov, MAX_OV, vre_limits);
if (s <= VRE_ERROR_NOMATCH) {
if (s < VRE_ERROR_NOMATCH)
VSLb(ctx->vsl, SLT_VCL_Error,
......@@ -237,10 +254,32 @@ backref(VRT_CTX, VCL_INT refnum, VCL_STRING fallback, struct vmod_priv *task)
return substr;
}
static inline const struct vre_limits *
get_limits(const struct vmod_re_regex *re, struct vre_limits *limits,
VCL_INT limit, VCL_INT limit_recursion)
{
if (limit <= 0 && limit_recursion <= 0)
return (&re->vre_limits);
if (limit > 0)
limits->match = limit;
else
limits->match = re->vre_limits.match;
if (limit_recursion > 0)
limits->match_recursion = limit_recursion;
else
limits->match_recursion = re->vre_limits.match_recursion;
return (limits);
}
VCL_BOOL
vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject)
vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject,
VCL_INT limit, VCL_INT limit_recursion)
{
struct vmod_priv *task;
struct vre_limits buf;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(re, VMOD_RE_REGEX_MAGIC);
......@@ -249,7 +288,9 @@ vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject)
task = VRT_priv_task(ctx, re);
AN(task);
task->len = 0;
return match(ctx, re->vre, subject, task);
return match(ctx, re->vre, subject, task,
get_limits(re, &buf, limit, limit_recursion));
}
VCL_STRING
......@@ -266,16 +307,32 @@ vmod_regex_backref(VRT_CTX, struct vmod_re_regex *re, VCL_INT refnum,
VCL_BOOL
vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
VCL_STRING subject)
VCL_STRING subject, VCL_INT limit, VCL_INT limit_recursion)
{
vre_t *vre;
int erroffset;
const char *error;
VCL_BOOL dyn_return;
struct vre_limits limits;
AN(pattern);
AN(task);
if (limit < 1) {
errmsg(ctx, "vmod re: invalid limit %d for regex \"%s\"",
limit, pattern);
return 0;
}
if (limit_recursion < 1) {
errmsg(ctx, "vmod re: invalid limit_recursion %d "
"for regex \"%s\"", limit_recursion, pattern);
return 0;
}
limits.match = limit;
limits.match_recursion = limit_recursion;
task->len = 0;
vre = VRE_compile(pattern, 0, &error, &erroffset);
if (vre == NULL) {
......@@ -284,7 +341,9 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
pattern, error, erroffset);
return 0;
}
dyn_return = match(ctx, vre, subject, task);
dyn_return = match(ctx, vre, subject, task, &limits);
VRE_free(&vre);
return dyn_return;
}
......
......@@ -89,7 +89,7 @@ since it re-uses the compiled expression obtained at VCL
initialization. So if you are matching against a fixed pattern that
never changes during the lifetime of VCL, use ``match``.
$Object regex(STRING)
$Object regex(STRING, INT limit=1000, INT limit_recursion=1000)
Description
Create a regex object with the given regular expression. The
......@@ -100,16 +100,34 @@ Description
If the regular expression fails to compile, then the VCL
load fails with an error message describing the problem.
The optional parameters ``limit`` and ``limit_recursion`` are
per-object defaults for the respective parameters of the
`func_regex.match`_ and `func_match_dyn`_ mehods.
Example
``new myregex = re.regex("\bmax-age\s*=\s*(\d+)");``
$Method BOOL .match(STRING)
$Method BOOL .match(STRING, INT limit=0, INT limit_recursion=0)
Description
Determines whether the given string matches the regex compiled
by the constructor; functionally equivalent to VCL's infix
operator ``~``.
The optional parameter ``limit`` restricts the number of
internal matching function calls in a ``pcre_exec()``
execution, analoguous to the varnishd
``pcre_match_limit`` parameter. For the default
value 0, the ``limit`` given to the constructor `obj_regex`_
is used.
The optional parameter ``limit_recursion`` restricts the
number of internal matching function recursions in a
``pcre_exec()`` execution, analoguous to the varnishd
``pcre_match_limit_recursion`` parameter. For the default
value 0, the ``limit_recursion`` given to the constructor
`obj_regex`_ is used.
Example
``if (myregex.match(beresp.http.Surrogate-Control)) { # ...``
......@@ -139,7 +157,8 @@ Description
Example
``set beresp.ttl = std.duration(myregex.backref(1, "120"), 120s);``
$Function BOOL match_dyn(PRIV_TASK, STRING, STRING)
$Function BOOL match_dyn(PRIV_TASK, STRING, STRING,
INT limit=1000, INT limit_recursion=1000)
Description
Compiles the regular expression given in the first argument,
......@@ -151,6 +170,10 @@ Description
with the tag ``VCL_Error``, and ``match_dyn`` returns
``false``.
For parameters ``limit`` and ``limit_recursion`` see
`func_regex.match`_, except that there is no object to inherit
defaults from.
Example
``if (re.match_dyn(req.http.Foo + "(\d+)", beresp.http.Bar)) { # ...``
......
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