[master] 97e6818ab vav: Prevent backslash-related overflows

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Jul 5 15:47:04 UTC 2021


commit 97e6818ab6562bb7008d370d683bf2a2a0d1a49a
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Mon Jul 5 07:50:30 2021 +0200

    vav: Prevent backslash-related overflows

diff --git a/lib/libvarnish/vav.c b/lib/libvarnish/vav.c
index a25ed58fc..7dc269aac 100644
--- a/lib/libvarnish/vav.c
+++ b/lib/libvarnish/vav.c
@@ -52,13 +52,21 @@
 #include "vas.h"
 #include "vav.h"
 
-int
-VAV_BackSlash(const char *s, char *res)
+static int
+vav_backslash_txt(const char *s, const char *e, char *res)
 {
-	int r;
+	int r, l;
 	char c;
 	unsigned u;
 
+	AN(s);
+	if (e == NULL)
+		e = strchr(s, '\0');
+
+	l = pdiff(s, e);
+	if (l < 2)
+		return (0);
+
 	assert(*s == '\\');
 	r = c = 0;
 	switch (s[1]) {
@@ -84,7 +92,7 @@ VAV_BackSlash(const char *s, char *res)
 		break;
 	case '0': case '1': case '2': case '3':
 	case '4': case '5': case '6': case '7':
-		for (r = 1; r < 4; r++) {
+		for (r = 1; r < 4 && r < l; r++) {
 			if (!isdigit(s[r]))
 				break;
 			if (s[r] - '0' > 7)
@@ -94,7 +102,7 @@ VAV_BackSlash(const char *s, char *res)
 		}
 		break;
 	case 'x':
-		if (1 == sscanf(s + 1, "x%02x", &u)) {
+		if (l >= 4 && sscanf(s + 1, "x%02x", &u) == 1) {
 			AZ(u & ~0xff);
 			c = u;	/*lint !e734 loss of precision */
 			r = 4;
@@ -108,6 +116,13 @@ VAV_BackSlash(const char *s, char *res)
 	return (r);
 }
 
+int
+VAV_BackSlash(const char *s, char *res)
+{
+
+	return (vav_backslash_txt(s, NULL, res));
+}
+
 char *
 VAV_BackSlashDecode(const char *s, const char *e)
 {
@@ -126,7 +141,12 @@ VAV_BackSlashDecode(const char *s, const char *e)
 			*r++ = *q++;
 			continue;
 		}
-		i = VAV_BackSlash(q, r);
+		i = vav_backslash_txt(q, e, r);
+		if (i == 0) {
+			free(p);
+			errno = EINVAL;
+			return (NULL);
+		}
 		q += i;
 		r++;
 	}
@@ -170,11 +190,7 @@ VAV_ParseTxt(const char *b, const char *e, int *argc, int flag)
 		}
 		while (b < e) {
 			if (*b == '\\' && !(flag & ARGV_NOESC)) {
-				if (b + 1 >= e) {
-					argv[0] = err_invalid_backslash;
-					return (argv);
-				}
-				i = VAV_BackSlash(b, NULL);
+				i = vav_backslash_txt(b, e, NULL);
 				if (i == 0) {
 					argv[0] = err_invalid_backslash;
 					return (argv);
@@ -183,7 +199,7 @@ VAV_ParseTxt(const char *b, const char *e, int *argc, int flag)
 				continue;
 			}
 			if (!quote) {
-				if (b >= e || isspace(*b))
+				if (isspace(*b))
 					break;
 				if ((flag & ARGV_COMMA) && *b == ',')
 					break;
@@ -207,10 +223,11 @@ VAV_ParseTxt(const char *b, const char *e, int *argc, int flag)
 			assert(argv[nargv] != NULL);
 			memcpy(argv[nargv], p, b - p);
 			argv[nargv][b - p] = '\0';
-			nargv++;
 		} else {
-			argv[nargv++] = VAV_BackSlashDecode(p, b);
+			argv[nargv] = VAV_BackSlashDecode(p, b);
+			assert(argv[nargv] != NULL);
 		}
+		nargv++;
 		if (b < e)
 			b++;
 	}
@@ -336,6 +353,9 @@ static const struct test_case *tests[] = {
 	TEST_PASS(K    , "foo #bar", "foo"),
 	TEST_PASS(    N, "\\", "\\"),
 	TEST_FAIL(0    , "\\", invalid_backslash),
+	TEST_FAIL(0    , "\\x", invalid_backslash),
+	TEST_FAIL(0    , "\\x2", invalid_backslash),
+	TEST_PASS(0    , "\\x20", " "),
 	TEST_FAIL(0    , "\"foo", missing_quote),
 	NULL
 #undef N


More information about the varnish-commit mailing list