Ian Kent ff6f3e
autofs-5.1.0 - fix buffer size checks in merge_options()
Ian Kent ff6f3e
Ian Kent ff6f3e
From: Ian Kent <raven@themaw.net>
Ian Kent ff6f3e
Ian Kent ff6f3e
Fix some buffer size overflow checks in merge_options().
Ian Kent ff6f3e
---
Ian Kent ff6f3e
 CHANGELOG        |    1 +
Ian Kent ff6f3e
 lib/parse_subs.c |   25 +++++++++++++++++++++----
Ian Kent ff6f3e
 2 files changed, 22 insertions(+), 4 deletions(-)
Ian Kent ff6f3e
Ian Kent ff6f3e
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent ff6f3e
index 92657c3..840e099 100644
Ian Kent ff6f3e
--- a/CHANGELOG
Ian Kent ff6f3e
+++ b/CHANGELOG
Ian Kent ff6f3e
@@ -12,6 +12,7 @@
Ian Kent ff6f3e
 - fix signed comparison in inet_fill_net().
Ian Kent ff6f3e
 - fix buffer size checks in get_network_proximity().
Ian Kent ff6f3e
 - fix leak in get_network_proximity().
Ian Kent ff6f3e
+- fix buffer size checks in merge_options().
Ian Kent ff6f3e
 
Ian Kent ff6f3e
 04/06/2014 autofs-5.1.0
Ian Kent ff6f3e
 =======================
Ian Kent ff6f3e
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
Ian Kent ff6f3e
index 6e9f2d7..6145828 100644
Ian Kent ff6f3e
--- a/lib/parse_subs.c
Ian Kent ff6f3e
+++ b/lib/parse_subs.c
Ian Kent ff6f3e
@@ -886,11 +886,11 @@ static char *hasopt(const char *str, const char *opt)
Ian Kent ff6f3e
 
Ian Kent ff6f3e
 char *merge_options(const char *opt1, const char *opt2)
Ian Kent ff6f3e
 {
Ian Kent ff6f3e
-	char str[MAX_OPTIONS_LEN];
Ian Kent ff6f3e
-	char result[MAX_OPTIONS_LEN];
Ian Kent ff6f3e
-	char neg[MAX_OPTION_LEN];
Ian Kent ff6f3e
+	char str[MAX_OPTIONS_LEN + 1];
Ian Kent ff6f3e
+	char result[MAX_OPTIONS_LEN + 1];
Ian Kent ff6f3e
+	char neg[MAX_OPTION_LEN + 1];
Ian Kent ff6f3e
 	char *tok, *ptr = NULL;
Ian Kent ff6f3e
-	size_t len;
Ian Kent ff6f3e
+	size_t resultlen, len;
Ian Kent ff6f3e
 
Ian Kent ff6f3e
 	if ((!opt1 || !*opt1) && (!opt2 || !*opt2))
Ian Kent ff6f3e
 		return NULL;
Ian Kent ff6f3e
@@ -910,9 +910,12 @@ char *merge_options(const char *opt1, const char *opt2)
Ian Kent ff6f3e
 	if (!strcmp(opt1, opt2))
Ian Kent ff6f3e
 		return strdup(opt1);
Ian Kent ff6f3e
 
Ian Kent ff6f3e
+	if (strlen(str) > MAX_OPTIONS_LEN)
Ian Kent ff6f3e
+		return NULL;
Ian Kent ff6f3e
 	memset(result, 0, sizeof(result));
Ian Kent ff6f3e
 	strcpy(str, opt1);
Ian Kent ff6f3e
 
Ian Kent ff6f3e
+	resultlen = 0;
Ian Kent ff6f3e
 	tok = strtok_r(str, ",", &ptr);
Ian Kent ff6f3e
 	while (tok) {
Ian Kent ff6f3e
 		const char *this = (const char *) tok;
Ian Kent ff6f3e
@@ -920,12 +923,15 @@ char *merge_options(const char *opt1, const char *opt2)
Ian Kent ff6f3e
 		if (eq) {
Ian Kent ff6f3e
 			*eq = '\0';
Ian Kent ff6f3e
 			if (!hasopt(opt2, this)) {
Ian Kent ff6f3e
+				if (resultlen + strlen(this) > MAX_OPTIONS_LEN)
Ian Kent ff6f3e
+					return NULL;
Ian Kent ff6f3e
 				*eq = '=';
Ian Kent ff6f3e
 				if (!*result)
Ian Kent ff6f3e
 					strcpy(result, this);
Ian Kent ff6f3e
 				else
Ian Kent ff6f3e
 					strcat(result, this);
Ian Kent ff6f3e
 				strcat(result, ",");
Ian Kent ff6f3e
+				resultlen += strlen(this) + 1;
Ian Kent ff6f3e
 				goto next;
Ian Kent ff6f3e
 			}
Ian Kent ff6f3e
 		}
Ian Kent ff6f3e
@@ -946,10 +952,14 @@ char *merge_options(const char *opt1, const char *opt2)
Ian Kent ff6f3e
 			goto next;
Ian Kent ff6f3e
 
Ian Kent ff6f3e
 		if (!strncmp(this, "no", 2)) {
Ian Kent ff6f3e
+			if (strlen(this + 2) > MAX_OPTION_LEN)
Ian Kent ff6f3e
+				return NULL;
Ian Kent ff6f3e
 			strcpy(neg, this + 2);
Ian Kent ff6f3e
 			if (hasopt(opt2, neg))
Ian Kent ff6f3e
 				goto next;
Ian Kent ff6f3e
 		} else {
Ian Kent ff6f3e
+			if ((strlen(this) + 2) > MAX_OPTION_LEN)
Ian Kent ff6f3e
+				return NULL;
Ian Kent ff6f3e
 			strcpy(neg, "no");
Ian Kent ff6f3e
 			strcat(neg, this);
Ian Kent ff6f3e
 			if (hasopt(opt2, neg))
Ian Kent ff6f3e
@@ -959,15 +969,22 @@ char *merge_options(const char *opt1, const char *opt2)
Ian Kent ff6f3e
 		if (hasopt(opt2, tok))
Ian Kent ff6f3e
 			goto next;
Ian Kent ff6f3e
 
Ian Kent ff6f3e
+		if (resultlen + strlen(this) + 1 > MAX_OPTIONS_LEN)
Ian Kent ff6f3e
+			return NULL;
Ian Kent ff6f3e
+
Ian Kent ff6f3e
 		if (!*result)
Ian Kent ff6f3e
 			strcpy(result, this);
Ian Kent ff6f3e
 		else
Ian Kent ff6f3e
 			strcat(result, this);
Ian Kent ff6f3e
 		strcat(result, ",");
Ian Kent ff6f3e
+		resultlen =+ strlen(this) + 1;
Ian Kent ff6f3e
 next:
Ian Kent ff6f3e
 		tok = strtok_r(NULL, ",", &ptr);
Ian Kent ff6f3e
 	}
Ian Kent ff6f3e
 
Ian Kent ff6f3e
+	if (resultlen + strlen(opt2) > MAX_OPTIONS_LEN)
Ian Kent ff6f3e
+		return NULL;
Ian Kent ff6f3e
+
Ian Kent ff6f3e
 	if (!*result)
Ian Kent ff6f3e
 		strcpy(result, opt2);
Ian Kent ff6f3e
 	else