[master] 3fdce6cf2 VRE: bounds check back references in VRE_sub()

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Aug 2 09:55:07 UTC 2021


commit 3fdce6cf2c4d360c27c98d05e530d39317d23c68
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Mon Aug 2 10:49:41 2021 +0200

    VRE: bounds check back references in VRE_sub()
    
    Before 6014912e74de7989e37b7be2737cef370b7147ba, VRE_sub() used an
    ovector of size 30, which always containted sufficient space to store
    the 10 possible back- references \0 thorugh \9.
    
    Now that we use pcre2_match_data_create_from_pattern() and later
    pcre2_get_ovector_pointer(), we only get space for the number of
    substrings in the pattern, see pcre2api(3):
    
            The ovector is created to be exactly the right size to hold
            all the substrings a pattern might capture.
    
    Consequently, we need to check that back references do not exceed the
    maximum ovector.

diff --git a/bin/varnishtest/tests/c00001.vtc b/bin/varnishtest/tests/c00001.vtc
index e301e4d09..5a338b2fb 100644
--- a/bin/varnishtest/tests/c00001.vtc
+++ b/bin/varnishtest/tests/c00001.vtc
@@ -23,6 +23,8 @@ varnish v1 -vcl+backend {
 		    regsub(beresp.http.Foobar, "(b)(a)(r)(f)", "\4\&\3\2p\");
 		set beresp.http.Snafu7 =
 		    regsub(beresp.http.Foobar, "ar", bereq.http.nosuchheader);
+		set beresp.http.inval =
+		    regsub(beresp.http.Foobar, "(b)(a)(r)f", "\9\8\7\6\5\4\3\2p");
 	}
 } -start
 
@@ -40,4 +42,5 @@ client c1 {
 	expect resp.http.snafu5 == "_barffra\\p_"
 	expect resp.http.snafu6 == "_f&rap\\_"
 	expect resp.http.snafu7 == "_bf_"
+	expect resp.http.inval == "_rap_"
 } -run
diff --git a/lib/libvarnish/vre.c b/lib/libvarnish/vre.c
index dd8eb70c3..9a8d2cc24 100644
--- a/lib/libvarnish/vre.c
+++ b/lib/libvarnish/vre.c
@@ -231,6 +231,7 @@ VRE_sub(const vre_t *code, const char *subject, const char *replacement,
 {
 	pcre2_match_data *data = NULL;
 	PCRE2_SIZE *ovector;
+	uint32_t nov;
 	int i, l;
 	const char *s;
 	unsigned x;
@@ -250,6 +251,7 @@ VRE_sub(const vre_t *code, const char *subject, const char *replacement,
 	do {
 		AN(data);
 		ovector = pcre2_get_ovector_pointer(data);
+		nov = pcre2_get_ovector_count(data);
 		AN(ovector);
 
 		/* Copy prefix to match */
@@ -262,6 +264,8 @@ VRE_sub(const vre_t *code, const char *subject, const char *replacement,
 			s++;
 			if (isdigit(*s)) {
 				x = *s - '0';
+				if (x >= nov)
+					continue;
 				l = ovector[2*x+1] - ovector[2*x];
 				VSB_bcat(vsb, subject + ovector[2*x], l);
 				continue;


More information about the varnish-commit mailing list