[3.0] 29d126f Avoid infinite loop in regsuball

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


commit 29d126fd6674cdfc12b1bf1378cca5dbb6d63c0a
Author: Tollef Fog Heen <tfheen at varnish-software.com>
Date:   Tue Nov 1 09:25:22 2011 +0100

    Avoid infinite loop in regsuball
    
    Also optimise out a few strlen calls in favour of just tracking the
    lengths.
    
    Fixes: #1047

diff --git a/bin/varnishd/cache_vrt_re.c b/bin/varnishd/cache_vrt_re.c
index 30ae5ca..fe6b814 100644
--- a/bin/varnishd/cache_vrt_re.c
+++ b/bin/varnishd/cache_vrt_re.c
@@ -95,13 +95,16 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
 	char *b0;
 	const char *s;
 	unsigned u, x;
+	int options = 0;
+	size_t len;
 
 	AN(re);
 	if (str == NULL)
 		str = "";
 	t = re;
 	memset(ovector, 0, sizeof(ovector));
-	i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30,
+	len = strlen(str);
+	i = VRE_exec(t, str, len, 0, options, ovector, 30,
 	    &params->vre_limits);
 
 	/* If it didn't match, we can return the original string */
@@ -137,10 +140,12 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
 			}
 		}
 		str += ovector[1];
+		len -= ovector[1];
 		if (!all)
 			break;
 		memset(&ovector, 0, sizeof(ovector));
-		i = VRE_exec(t, str, strlen(str), 0, 0, ovector, 30,
+		options |= VRE_NOTEMPTY_ATSTART;
+		i = VRE_exec(t, str, len, 0, options, ovector, 30,
 		    &params->vre_limits);
 		if (i < VRE_ERROR_NOMATCH ) {
 			WSP(sp, SLT_VCL_error,
@@ -150,8 +155,7 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
 	} while (i != VRE_ERROR_NOMATCH);
 
 	/* Copy suffix to match */
-	l = strlen(str) + 1;
-	Tadd(&res, str, l);
+	Tadd(&res, str, len+1);
 	if (res.b >= res.e) {
 		WS_Release(sp->http->ws, 0);
 		return (str);
diff --git a/bin/varnishtest/tests/c00047.vtc b/bin/varnishtest/tests/c00047.vtc
new file mode 100644
index 0000000..4b23194
--- /dev/null
+++ b/bin/varnishtest/tests/c00047.vtc
@@ -0,0 +1,33 @@
+varnishtest "Test VCL regsuball()"
+
+server s1 {
+	rxreq 
+	txresp \
+		-hdr "foo: barbar" \
+		-hdr "bar: bbbar"
+} -start
+
+varnish v1 -vcl+backend { 
+	sub vcl_fetch {
+		set beresp.http.baz1 = regsuball(beresp.http.foo, "barb", "zz");
+		set beresp.http.baz2 = regsuball(beresp.http.foo, "ar", "zz");
+		set beresp.http.baz3 = regsuball(beresp.http.foo, "^", "baz");
+		set beresp.http.baz4 = regsuball(beresp.http.foo, "^[;]*", "baz");
+		set beresp.http.baz5 = regsuball(beresp.http.bar, "^b*", "b");
+		set beresp.http.baz6 = regsuball(beresp.http.foo, "^b*", "z");
+		set beresp.http.baz7 = regsuball(beresp.http.foo, "ping", "pong");
+	}
+} -start 
+
+client c1 {
+	txreq -url "/"
+	rxresp
+	expect resp.status == 200
+	expect resp.http.baz1 == "zzar"
+	expect resp.http.baz2 == "bzzbzz"
+	expect resp.http.baz3 == "bazbarbar"
+	expect resp.http.baz4 == "bazbarbar"
+	expect resp.http.baz5 == "bar"
+	expect resp.http.baz6 == "zarbar"
+	expect resp.http.baz7 == "barbar"
+} -run
diff --git a/include/vre.h b/include/vre.h
index 29c1b08..a1206e5 100644
--- a/include/vre.h
+++ b/include/vre.h
@@ -49,6 +49,7 @@ typedef struct vre vre_t;
 
 /* And those to PCRE options */
 #define VRE_CASELESS           0x00000001
+#define VRE_NOTEMPTY_ATSTART   0x10000000
 
 vre_t *VRE_compile(const char *, int, const char **, int *);
 int VRE_exec(const vre_t *code, const char *subject, int length,



More information about the varnish-commit mailing list