Blame SOURCES/0087-RHBZ-1110013-config-error-checking.patch

1eb31d
---
1eb31d
 libmultipath/parser.c |  154 ++++++++++++++++++++++++++++++++++++++++----------
1eb31d
 1 file changed, 126 insertions(+), 28 deletions(-)
1eb31d
1eb31d
Index: multipath-tools-130222/libmultipath/parser.c
1eb31d
===================================================================
1eb31d
--- multipath-tools-130222.orig/libmultipath/parser.c
1eb31d
+++ multipath-tools-130222/libmultipath/parser.c
1eb31d
@@ -395,36 +395,57 @@ set_value(vector strvec)
1eb31d
 	char *alloc = NULL;
1eb31d
 	char *tmp;
1eb31d
 
1eb31d
-	if (!str)
1eb31d
+	if (!str) {
1eb31d
+		condlog(0, "option '%s' missing value",
1eb31d
+			(char *)VECTOR_SLOT(strvec, 0));
1eb31d
 		return NULL;
1eb31d
-
1eb31d
+	}
1eb31d
 	size = strlen(str);
1eb31d
-	if (size == 0)
1eb31d
+	if (size == 0) {
1eb31d
+		condlog(0, "option '%s' has empty value",
1eb31d
+			(char *)VECTOR_SLOT(strvec, 0));
1eb31d
 		return NULL;
1eb31d
-
1eb31d
-	if (*str == '"') {
1eb31d
-		for (i = 2; i < VECTOR_SIZE(strvec); i++) {
1eb31d
-			str = VECTOR_SLOT(strvec, i);
1eb31d
-			len += strlen(str);
1eb31d
-			if (!alloc)
1eb31d
-				alloc =
1eb31d
-				    (char *) MALLOC(sizeof (char *) *
1eb31d
-						    (len + 1));
1eb31d
-			else {
1eb31d
-				alloc =
1eb31d
-				    REALLOC(alloc, sizeof (char *) * (len + 1));
1eb31d
-				tmp = VECTOR_SLOT(strvec, i-1);
1eb31d
-				if (alloc && *str != '"' && *tmp != '"')
1eb31d
-					strncat(alloc, " ", 1);
1eb31d
-			}
1eb31d
-
1eb31d
-			if (alloc && i != VECTOR_SIZE(strvec)-1)
1eb31d
-				strncat(alloc, str, strlen(str));
1eb31d
-		}
1eb31d
-	} else {
1eb31d
-		alloc = MALLOC(sizeof (char *) * (size + 1));
1eb31d
+	}
1eb31d
+	if (*str != '"') {
1eb31d
+		alloc = MALLOC(sizeof (char) * (size + 1));
1eb31d
 		if (alloc)
1eb31d
 			memcpy(alloc, str, size);
1eb31d
+		else
1eb31d
+			condlog(0, "can't allocate memeory for option '%s'",
1eb31d
+				(char *)VECTOR_SLOT(strvec, 0));
1eb31d
+		return alloc;
1eb31d
+	}
1eb31d
+	/* Even empty quotes counts as a value (An empty string) */
1eb31d
+	alloc = (char *) MALLOC(sizeof (char));
1eb31d
+	if (!alloc) {
1eb31d
+		condlog(0, "can't allocate memeory for option '%s'",
1eb31d
+			(char *)VECTOR_SLOT(strvec, 0));
1eb31d
+		return NULL;
1eb31d
+	}
1eb31d
+	for (i = 2; i < VECTOR_SIZE(strvec); i++) {
1eb31d
+		str = VECTOR_SLOT(strvec, i);
1eb31d
+		if (!str) {
1eb31d
+			free(alloc);
1eb31d
+			condlog(0, "parse error for option '%s'",
1eb31d
+				(char *)VECTOR_SLOT(strvec, 0));
1eb31d
+			return NULL;
1eb31d
+		}
1eb31d
+		if (*str == '"')
1eb31d
+			break;
1eb31d
+		tmp = alloc;
1eb31d
+		/* The first +1 is for the NULL byte. The rest are for the
1eb31d
+		 * spaces between words */
1eb31d
+		len += strlen(str) + 1;
1eb31d
+		alloc = REALLOC(alloc, sizeof (char) * len);
1eb31d
+		if (!alloc) {
1eb31d
+			FREE(tmp);
1eb31d
+			condlog(0, "can't allocate memeory for option '%s'",
1eb31d
+				(char *)VECTOR_SLOT(strvec, 0));
1eb31d
+			return NULL;
1eb31d
+		}
1eb31d
+		if (*alloc != '\0')
1eb31d
+			strncat(alloc, " ", 1);
1eb31d
+		strncat(alloc, str, strlen(str));
1eb31d
 	}
1eb31d
 	return alloc;
1eb31d
 }
1eb31d
@@ -465,6 +486,74 @@ void free_uniques(vector uniques)
1eb31d
 }
1eb31d
 
1eb31d
 int
1eb31d
+is_sublevel_keyword(char *str)
1eb31d
+{
1eb31d
+	return (strcmp(str, "defaults") == 0 || strcmp(str, "blacklist") == 0 ||
1eb31d
+		strcmp(str, "blacklist_exceptions") == 0 ||
1eb31d
+		strcmp(str, "devices") == 0 || strcmp(str, "devices") == 0 ||
1eb31d
+		strcmp(str, "device") == 0 || strcmp(str, "multipaths") == 0 ||
1eb31d
+		strcmp(str, "multipath") == 0);
1eb31d
+}
1eb31d
+
1eb31d
+int
1eb31d
+validate_config_strvec(vector strvec)
1eb31d
+{
1eb31d
+	char *str;
1eb31d
+	int i;
1eb31d
+
1eb31d
+	str = VECTOR_SLOT(strvec, 0);
1eb31d
+	if (str == NULL) {
1eb31d
+		condlog(0, "can't parse option on line %d of config file",
1eb31d
+			line_nr);
1eb31d
+	return -1;
1eb31d
+	}
1eb31d
+	if (*str == '}') {
1eb31d
+		if (VECTOR_SIZE(strvec) > 1)
1eb31d
+			condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr);
1eb31d
+		return 0;
1eb31d
+	}
1eb31d
+	if (*str == '{') {
1eb31d
+		condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr);
1eb31d
+		return -1;
1eb31d
+	}
1eb31d
+	if (is_sublevel_keyword(str)) {
1eb31d
+		str = VECTOR_SLOT(strvec, 1);
1eb31d
+		if (str == NULL)
1eb31d
+			condlog(0, "missing '{' on line %d of config file", line_nr);
1eb31d
+		else if (*str != '{')
1eb31d
+			condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str);
1eb31d
+		else if (VECTOR_SIZE(strvec) > 2)
1eb31d
+			condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
1eb31d
+		return 0;
1eb31d
+	}
1eb31d
+	str = VECTOR_SLOT(strvec, 1);
1eb31d
+	if (str == NULL) {
1eb31d
+		condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr);
1eb31d
+		return -1;
1eb31d
+	}
1eb31d
+	if (*str != '"') {
1eb31d
+		if (VECTOR_SIZE(strvec) > 2)
1eb31d
+			condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
1eb31d
+		return 0;
1eb31d
+	}
1eb31d
+	for (i = 2; i < VECTOR_SIZE(strvec); i++) {
1eb31d
+		str = VECTOR_SLOT(strvec, i);
1eb31d
+		if (str == NULL) {
1eb31d
+			condlog(0, "can't parse value on line %d of config file", line_nr);
1eb31d
+			return -1;
1eb31d
+		}
1eb31d
+		if (*str == '"') {
1eb31d
+			if (VECTOR_SIZE(strvec) > i + 1)
1eb31d
+				condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr);
1eb31d
+			return 0;
1eb31d
+		}
1eb31d
+	}
1eb31d
+	condlog(0, "missing closing quotes on line %d of config file",
1eb31d
+		line_nr);
1eb31d
+	return 0;
1eb31d
+}
1eb31d
+
1eb31d
+int
1eb31d
 process_stream(vector keywords)
1eb31d
 {
1eb31d
 	int i;
1eb31d
@@ -494,11 +583,20 @@ process_stream(vector keywords)
1eb31d
 		if (!strvec)
1eb31d
 			continue;
1eb31d
 
1eb31d
+		if (validate_config_strvec(strvec) != 0) {
1eb31d
+			free_strvec(strvec);
1eb31d
+			continue;
1eb31d
+		}
1eb31d
+
1eb31d
 		str = VECTOR_SLOT(strvec, 0);
1eb31d
 
1eb31d
-		if (!strcmp(str, EOB) && kw_level > 0) {
1eb31d
-			free_strvec(strvec);
1eb31d
-			break;
1eb31d
+		if (!strcmp(str, EOB)) {
1eb31d
+			if (kw_level > 0) {
1eb31d
+				free_strvec(strvec);
1eb31d
+				break;
1eb31d
+			}
1eb31d
+			condlog(0, "unmatched '%s' at line %d of config file",
1eb31d
+				EOB, line_nr);
1eb31d
 		}
1eb31d
 
1eb31d
 		for (i = 0; i < VECTOR_SIZE(keywords); i++) {