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``. ...@@ -106,8 +106,8 @@ never changes during the lifetime of VCL, use ``match``.
CONTENTS CONTENTS
======== ========
* regex(STRING) * regex(STRING, INT, INT)
* BOOL match_dyn(STRING, STRING) * BOOL match_dyn(STRING, STRING, INT, INT)
* STRING backref_dyn(INT, STRING) * STRING backref_dyn(INT, STRING)
* STRING version() * STRING version()
...@@ -118,7 +118,7 @@ regex ...@@ -118,7 +118,7 @@ regex
:: ::
new OBJ = regex(STRING) new OBJ = regex(STRING, INT limit=1000, INT limit_recursion=1000)
Description Description
Create a regex object with the given regular expression. The Create a regex object with the given regular expression. The
...@@ -129,6 +129,10 @@ Description ...@@ -129,6 +129,10 @@ Description
If the regular expression fails to compile, then the VCL If the regular expression fails to compile, then the VCL
load fails with an error message describing the problem. 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 Example
``new myregex = re.regex("\bmax-age\s*=\s*(\d+)");`` ``new myregex = re.regex("\bmax-age\s*=\s*(\d+)");``
...@@ -139,13 +143,27 @@ regex.match ...@@ -139,13 +143,27 @@ regex.match
:: ::
BOOL regex.match(STRING) BOOL regex.match(STRING, INT limit=0, INT limit_recursion=0)
Description Description
Determines whether the given string matches the regex compiled Determines whether the given string matches the regex compiled
by the constructor; functionally equivalent to VCL's infix by the constructor; functionally equivalent to VCL's infix
operator ``~``. 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 Example
``if (myregex.match(beresp.http.Surrogate-Control)) { # ...`` ``if (myregex.match(beresp.http.Surrogate-Control)) { # ...``
...@@ -189,7 +207,7 @@ match_dyn ...@@ -189,7 +207,7 @@ match_dyn
:: ::
BOOL match_dyn(STRING, STRING) BOOL match_dyn(STRING, STRING, INT limit=1000, INT limit_recursion=1000)
Description Description
Compiles the regular expression given in the first argument, Compiles the regular expression given in the first argument,
...@@ -201,6 +219,10 @@ Description ...@@ -201,6 +219,10 @@ Description
with the tag ``VCL_Error``, and ``match_dyn`` returns with the tag ``VCL_Error``, and ``match_dyn`` returns
``false``. ``false``.
For parameters ``limit`` and ``limit_recursion`` see
`func_regex.match`_, except that there is no object to inherit
defaults from.
Example Example
``if (re.match_dyn(req.http.Foo + "(\d+)", beresp.http.Bar)) { # ...`` ``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 varnish v1 -vcl { backend b { .host = "${bad_ip}"; } } -start
...@@ -10,3 +10,21 @@ varnish v1 -errvcl {vmod re: error compiling regex} { ...@@ -10,3 +10,21 @@ varnish v1 -errvcl {vmod re: error compiling regex} {
new paren = re.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);
}
}
...@@ -58,16 +58,17 @@ ...@@ -58,16 +58,17 @@
#define MAX_OV_USED ((MAX_MATCHES) * 2) #define MAX_OV_USED ((MAX_MATCHES) * 2)
struct vmod_re_regex { struct vmod_re_regex {
unsigned magic; unsigned magic;
#define VMOD_RE_REGEX_MAGIC 0x955706ee #define VMOD_RE_REGEX_MAGIC 0x955706ee
vre_t *vre; vre_t *vre;
struct vre_limits vre_limits;
}; };
typedef struct ov_s { typedef struct ov_s {
unsigned magic; unsigned magic;
#define OV_MAGIC 0x844bfa39 #define OV_MAGIC 0x844bfa39
const char *subject; const char *subject;
int ovector[MAX_OV_USED]; int ovector[MAX_OV_USED];
} ov_t; } ov_t;
static void static void
...@@ -93,7 +94,7 @@ errmsg(VRT_CTX, const char *fmt, ...) ...@@ -93,7 +94,7 @@ errmsg(VRT_CTX, const char *fmt, ...)
VCL_VOID VCL_VOID
vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name, 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; struct vmod_re_regex *re;
vre_t *vre; vre_t *vre;
...@@ -106,15 +107,31 @@ vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name, ...@@ -106,15 +107,31 @@ vmod_regex__init(VRT_CTX, struct vmod_re_regex **rep, const char *vcl_name,
AN(vcl_name); AN(vcl_name);
AN(pattern); 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 " errmsg(ctx, "vmod re: error compiling regex \"%s\" in %s "
"constructor: %s (at offset %d)", pattern, vcl_name, "constructor: %s (at offset %d)", pattern, vcl_name,
error, erroffset); error, erroffset);
return;
}
ALLOC_OBJ(re, VMOD_RE_REGEX_MAGIC); ALLOC_OBJ(re, VMOD_RE_REGEX_MAGIC);
AN(re); AN(re);
*rep = re;
re->vre = vre; re->vre = vre;
re->vre_limits.match = limit;
re->vre_limits.match_recursion = limit_recursion;
*rep = re;
} }
VCL_VOID VCL_VOID
...@@ -133,7 +150,8 @@ vmod_regex__fini(struct vmod_re_regex **rep) ...@@ -133,7 +150,8 @@ vmod_regex__fini(struct vmod_re_regex **rep)
} }
static VCL_BOOL 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; ov_t *ov;
int s, nov[MAX_OV]; int s, nov[MAX_OV];
...@@ -160,8 +178,7 @@ match(VRT_CTX, vre_t *vre, VCL_STRING subject, struct vmod_priv *task) ...@@ -160,8 +178,7 @@ match(VRT_CTX, vre_t *vre, VCL_STRING subject, struct vmod_priv *task)
} }
len = strlen(subject); len = strlen(subject);
s = VRE_exec(vre, subject, len, 0, 0, nov, MAX_OV, s = VRE_exec(vre, subject, len, 0, 0, nov, MAX_OV, vre_limits);
vparam_vre_limits);
if (s <= VRE_ERROR_NOMATCH) { if (s <= VRE_ERROR_NOMATCH) {
if (s < VRE_ERROR_NOMATCH) if (s < VRE_ERROR_NOMATCH)
VSLb(ctx->vsl, SLT_VCL_Error, VSLb(ctx->vsl, SLT_VCL_Error,
...@@ -237,10 +254,32 @@ backref(VRT_CTX, VCL_INT refnum, VCL_STRING fallback, struct vmod_priv *task) ...@@ -237,10 +254,32 @@ backref(VRT_CTX, VCL_INT refnum, VCL_STRING fallback, struct vmod_priv *task)
return substr; 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 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 vmod_priv *task;
struct vre_limits buf;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(re, VMOD_RE_REGEX_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) ...@@ -249,7 +288,9 @@ vmod_regex_match(VRT_CTX, struct vmod_re_regex *re, VCL_STRING subject)
task = VRT_priv_task(ctx, re); task = VRT_priv_task(ctx, re);
AN(task); AN(task);
task->len = 0; 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 VCL_STRING
...@@ -266,16 +307,32 @@ vmod_regex_backref(VRT_CTX, struct vmod_re_regex *re, VCL_INT refnum, ...@@ -266,16 +307,32 @@ vmod_regex_backref(VRT_CTX, struct vmod_re_regex *re, VCL_INT refnum,
VCL_BOOL VCL_BOOL
vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern, 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; vre_t *vre;
int erroffset; int erroffset;
const char *error; const char *error;
VCL_BOOL dyn_return; VCL_BOOL dyn_return;
struct vre_limits limits;
AN(pattern); AN(pattern);
AN(task); 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; task->len = 0;
vre = VRE_compile(pattern, 0, &error, &erroffset); vre = VRE_compile(pattern, 0, &error, &erroffset);
if (vre == NULL) { if (vre == NULL) {
...@@ -284,7 +341,9 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern, ...@@ -284,7 +341,9 @@ vmod_match_dyn(VRT_CTX, struct vmod_priv *task, VCL_STRING pattern,
pattern, error, erroffset); pattern, error, erroffset);
return 0; return 0;
} }
dyn_return = match(ctx, vre, subject, task);
dyn_return = match(ctx, vre, subject, task, &limits);
VRE_free(&vre); VRE_free(&vre);
return dyn_return; return dyn_return;
} }
......
...@@ -89,7 +89,7 @@ since it re-uses the compiled expression obtained at VCL ...@@ -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 initialization. So if you are matching against a fixed pattern that
never changes during the lifetime of VCL, use ``match``. never changes during the lifetime of VCL, use ``match``.
$Object regex(STRING) $Object regex(STRING, INT limit=1000, INT limit_recursion=1000)
Description Description
Create a regex object with the given regular expression. The Create a regex object with the given regular expression. The
...@@ -100,16 +100,34 @@ Description ...@@ -100,16 +100,34 @@ Description
If the regular expression fails to compile, then the VCL If the regular expression fails to compile, then the VCL
load fails with an error message describing the problem. 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 Example
``new myregex = re.regex("\bmax-age\s*=\s*(\d+)");`` ``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 Description
Determines whether the given string matches the regex compiled Determines whether the given string matches the regex compiled
by the constructor; functionally equivalent to VCL's infix by the constructor; functionally equivalent to VCL's infix
operator ``~``. 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 Example
``if (myregex.match(beresp.http.Surrogate-Control)) { # ...`` ``if (myregex.match(beresp.http.Surrogate-Control)) { # ...``
...@@ -139,7 +157,8 @@ Description ...@@ -139,7 +157,8 @@ Description
Example Example
``set beresp.ttl = std.duration(myregex.backref(1, "120"), 120s);`` ``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 Description
Compiles the regular expression given in the first argument, Compiles the regular expression given in the first argument,
...@@ -151,6 +170,10 @@ Description ...@@ -151,6 +170,10 @@ Description
with the tag ``VCL_Error``, and ``match_dyn`` returns with the tag ``VCL_Error``, and ``match_dyn`` returns
``false``. ``false``.
For parameters ``limit`` and ``limit_recursion`` see
`func_regex.match`_, except that there is no object to inherit
defaults from.
Example Example
``if (re.match_dyn(req.http.Foo + "(\d+)", beresp.http.Bar)) { # ...`` ``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