[3.0] 62ab683 Make it possible to set limits for VRE matching.

Tollef Fog Heen tfheen at varnish-cache.org
Mon Apr 16 10:20:33 CEST 2012


commit 62ab6836a23294b4600027ca7396aaacc587230e
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Sep 22 12:15:52 2011 +0000

    Make it possible to set limits for VRE matching.

diff --git a/bin/varnishd/cache_vrt_re.c b/bin/varnishd/cache_vrt_re.c
index a02b6ff..30ae5ca 100644
--- a/bin/varnishd/cache_vrt_re.c
+++ b/bin/varnishd/cache_vrt_re.c
@@ -76,7 +76,7 @@ VRT_re_match(const struct sess *sp, const char *s, void *re)
 		s = "";
 	AN(re);
 	t = re;
-	i = VRE_exec(t, s, strlen(s), 0, 0, NULL, 0);
+	i = VRE_exec(t, s, strlen(s), 0, 0, NULL, 0, &params->vre_limits);
 	if (i >= 0)
 		return (1);
 	if (i < VRE_ERROR_NOMATCH )
@@ -101,7 +101,8 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
 		str = "";
 	t = re;
 	memset(ovector, 0, sizeof(ovector));
-	i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30);
+	i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30,
+	    &params->vre_limits);
 
 	/* If it didn't match, we can return the original string */
 	if (i == VRE_ERROR_NOMATCH)
@@ -139,7 +140,8 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
 		if (!all)
 			break;
 		memset(&ovector, 0, sizeof(ovector));
-		i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30);
+		i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30,
+		    &params->vre_limits);
 		if (i < VRE_ERROR_NOMATCH ) {
 			WSP(sp, SLT_VCL_error,
 			    "Regexp matching returned %d", i);
diff --git a/bin/varnishd/heritage.h b/bin/varnishd/heritage.h
index 6571e31..99d5747 100644
--- a/bin/varnishd/heritage.h
+++ b/bin/varnishd/heritage.h
@@ -30,6 +30,7 @@
  */
 
 #include <pthread.h>
+#include "vre.h"
 
 struct listen_sock {
 	VTAILQ_ENTRY(listen_sock)	list;
@@ -211,6 +212,8 @@ struct params {
 	double			critbit_cooloff;
 
 	double			shortlived;
+
+	struct vre_limits	vre_limits;
 };
 
 /*
diff --git a/bin/varnishd/mgt_param.c b/bin/varnishd/mgt_param.c
index 4ca1b7b..6113978 100644
--- a/bin/varnishd/mgt_param.c
+++ b/bin/varnishd/mgt_param.c
@@ -948,6 +948,24 @@ static const struct parspec input_parspec[] = {
 		"Unreferenced VCL objects result in error.\n",
 		0,
 		"on", "bool" },
+
+
+	{ "pcre_match_limit", tweak_uint,
+		&master.vre_limits.match,
+		1, UINT_MAX,
+		"The limit for the  number of internal matching function"
+		" calls in a pcre_exec() execution.",
+		0,
+		"10000", ""},
+
+	{ "pcre_match_limit_recursion", tweak_uint,
+		&master.vre_limits.match_recursion,
+		1, UINT_MAX,
+		"The limit for the  number of internal matching function"
+		" recursions in a pcre_exec() execution.",
+		0,
+		"10000", ""},
+
 	{ NULL, NULL, NULL }
 };
 
diff --git a/include/vre.h b/include/vre.h
index 47dea3f..29c1b08 100644
--- a/include/vre.h
+++ b/include/vre.h
@@ -27,9 +27,21 @@
  *
  * Regular expression support
  *
+ * We wrap PCRE in VRE to make to make it feasible to use something else
+ * without hunting down stuff through out the Varnish source code.
+ *
  */
 
+#ifndef VRE_H_INCLUDED
+#define VRE_H_INCLUDED
+
 struct vre;
+
+struct vre_limits {
+	unsigned	match;
+	unsigned	match_recursion;
+};
+
 typedef struct vre vre_t;
 
 /* This maps to PCRE error codes */
@@ -39,5 +51,9 @@ typedef struct vre vre_t;
 #define VRE_CASELESS           0x00000001
 
 vre_t *VRE_compile(const char *, int, const char **, int *);
-int VRE_exec(const vre_t *, const char *, int, int, int, int *, int);
+int VRE_exec(const vre_t *code, const char *subject, int length,
+    int startoffset, int options, int *ovector, int ovecsize,
+    const volatile struct vre_limits *lim);
 void VRE_free(vre_t **);
+
+#endif /* VRE_H_INCLUDED */
diff --git a/lib/libvarnish/vre.c b/lib/libvarnish/vre.c
index 667d177..68beaf8 100644
--- a/lib/libvarnish/vre.c
+++ b/lib/libvarnish/vre.c
@@ -27,6 +27,7 @@
  */
 
 #include <pcre.h>
+#include <string.h>
 
 #include "libvarnish.h"
 #include "miniobj.h"
@@ -58,17 +59,27 @@ VRE_compile(const char *pattern, int options,
 
 int
 VRE_exec(const vre_t *code, const char *subject, int length,
-    int startoffset, int options, int *ovector, int ovecsize)
+    int startoffset, int options, int *ovector, int ovecsize,
+    const volatile struct vre_limits *lim)
 {
 	CHECK_OBJ_NOTNULL(code, VRE_MAGIC);
 	int ov[30];
+	pcre_extra extra;
 
 	if (ovector == NULL) {
 		ovector = ov;
 		ovecsize = sizeof(ov)/sizeof(ov[0]);
 	}
 
-	return (pcre_exec(code->re, NULL, subject, length,
+	memset(&extra, 0, sizeof extra);
+	if (lim != NULL) {
+		extra.match_limit = lim->match;
+		extra.flags |= PCRE_EXTRA_MATCH_LIMIT;
+		extra.match_limit_recursion = lim->match_recursion;
+		extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
+	}
+
+	return (pcre_exec(code->re, &extra, subject, length,
 	    startoffset, options, ovector, ovecsize));
 }
 
diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c
index 6791888..8ffff30 100644
--- a/lib/libvarnishapi/vsl.c
+++ b/lib/libvarnishapi/vsl.c
@@ -258,13 +258,13 @@ VSL_NextLog(const struct VSM_data *vd, uint32_t **pp, uint64_t *bits)
 			continue;
 		if (vsl->regincl != NULL) {
 			i = VRE_exec(vsl->regincl, VSL_DATA(p), VSL_LEN(p),
-			    0, 0, NULL, 0);
+			    0, 0, NULL, 0, NULL);
 			if (i == VRE_ERROR_NOMATCH)
 				continue;
 		}
 		if (vsl->regexcl != NULL) {
 			i = VRE_exec(vsl->regexcl, VSL_DATA(p), VSL_LEN(p),
-			    0, 0, NULL, 0);
+			    0, 0, NULL, 0, NULL);
 			if (i != VRE_ERROR_NOMATCH)
 				continue;
 		}
@@ -274,7 +274,7 @@ VSL_NextLog(const struct VSM_data *vd, uint32_t **pp, uint64_t *bits)
 			VTAILQ_FOREACH(vrm, &vsl->matchers, next) {
 				if (vrm->tag == t) {
 					i = VRE_exec(vrm->re, VSL_DATA(p),
-						     VSL_LEN(p), 0, 0, NULL, 0);
+					    VSL_LEN(p), 0, 0, NULL, 0, NULL);
 					if (i >= 0)
 						*bits |= (uintmax_t)1 << j;
 				}



More information about the varnish-commit mailing list