Blame SOURCES/0117-libmultipath-cleanup-remove_feature.patch

8b67ad
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
8b67ad
From: Benjamin Marzinski <bmarzins@redhat.com>
8b67ad
Date: Fri, 7 Oct 2022 12:35:37 -0500
8b67ad
Subject: [PATCH] libmultipath: cleanup remove_feature
8b67ad
8b67ad
remove_feature() didn't correctly handle feature strings that used
8b67ad
whitespace other than spaces, which the kernel allows. It also didn't
8b67ad
check if the feature string to be removed was part of a larger feature
8b67ad
token. Finally, it did a lot of unnecessary work. By failing if the
8b67ad
feature string to be removed contains leading or trailing whitespace,
8b67ad
the function can be significanly simplified.
8b67ad
8b67ad
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
8b67ad
Reviewed-by: Martin Wilck <mwilck@suse.com>
8b67ad
---
8b67ad
 libmultipath/structs.c | 82 +++++++++++++++---------------------------
8b67ad
 1 file changed, 29 insertions(+), 53 deletions(-)
8b67ad
8b67ad
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
8b67ad
index 9f86eb69..471087e2 100644
8b67ad
--- a/libmultipath/structs.c
8b67ad
+++ b/libmultipath/structs.c
8b67ad
@@ -6,6 +6,7 @@
8b67ad
 #include <unistd.h>
8b67ad
 #include <libdevmapper.h>
8b67ad
 #include <libudev.h>
8b67ad
+#include <ctype.h>
8b67ad
 
8b67ad
 #include "checkers.h"
8b67ad
 #include "memory.h"
8b67ad
@@ -633,7 +634,7 @@ int add_feature(char **f, const char *n)
8b67ad
 
8b67ad
 int remove_feature(char **f, const char *o)
8b67ad
 {
8b67ad
-	int c = 0, d, l;
8b67ad
+	int c = 0, d;
8b67ad
 	char *e, *p, *n;
8b67ad
 	const char *q;
8b67ad
 
8b67ad
@@ -644,33 +645,35 @@ int remove_feature(char **f, const char *o)
8b67ad
 	if (!o || *o == '\0')
8b67ad
 		return 0;
8b67ad
 
8b67ad
-	/* Check if not present */
8b67ad
-	if (!strstr(*f, o))
8b67ad
+	d = strlen(o);
8b67ad
+	if (isspace(*o) || isspace(*(o + d - 1))) {
8b67ad
+		condlog(0, "internal error: feature \"%s\" has leading or trailing spaces", o);
8b67ad
+		return 1;
8b67ad
+	}
8b67ad
+
8b67ad
+	/* Check if present and not part of a larger feature token*/
8b67ad
+	p = *f + 1; /* the size must be at the start of the features string */
8b67ad
+	while ((p = strstr(p, o)) != NULL) {
8b67ad
+		if (isspace(*(p - 1)) &&
8b67ad
+		    (isspace(*(p + d)) || *(p + d) == '\0'))
8b67ad
+			break;
8b67ad
+		p += d;
8b67ad
+	}
8b67ad
+	if (!p)
8b67ad
 		return 0;
8b67ad
 
8b67ad
 	/* Get feature count */
8b67ad
 	c = strtoul(*f, &e, 10);
8b67ad
-	if (*f == e)
8b67ad
-		/* parse error */
8b67ad
+	if (*f == e || !isspace(*e)) {
8b67ad
+		condlog(0, "parse error in feature string \"%s\"", *f);
8b67ad
 		return 1;
8b67ad
-
8b67ad
-	/* Normalize features */
8b67ad
-	while (*o == ' ') {
8b67ad
-		o++;
8b67ad
 	}
8b67ad
-	/* Just spaces, return */
8b67ad
-	if (*o == '\0')
8b67ad
-		return 0;
8b67ad
-	q = o + strlen(o);
8b67ad
-	while (*q == ' ')
8b67ad
-		q--;
8b67ad
-	d = (int)(q - o);
8b67ad
 
8b67ad
 	/* Update feature count */
8b67ad
 	c--;
8b67ad
 	q = o;
8b67ad
-	while (q[0] != '\0') {
8b67ad
-		if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0')
8b67ad
+	while (*q != '\0') {
8b67ad
+		if (isspace(*q) && !isspace(*(q + 1)) && *(q + 1) != '\0')
8b67ad
 			c--;
8b67ad
 		q++;
8b67ad
 	}
8b67ad
@@ -684,15 +687,8 @@ int remove_feature(char **f, const char *o)
8b67ad
 		goto out;
8b67ad
 	}
8b67ad
 
8b67ad
-	/* Search feature to be removed */
8b67ad
-	e = strstr(*f, o);
8b67ad
-	if (!e)
8b67ad
-		/* Not found, return */
8b67ad
-		return 0;
8b67ad
-
8b67ad
 	/* Update feature count space */
8b67ad
-	l = strlen(*f) - d;
8b67ad
-	n =  MALLOC(l + 1);
8b67ad
+	n =  MALLOC(strlen(*f) - d + 1);
8b67ad
 	if (!n)
8b67ad
 		return 1;
8b67ad
 
8b67ad
@@ -702,36 +698,16 @@ int remove_feature(char **f, const char *o)
8b67ad
 	 * Copy existing features up to the feature
8b67ad
 	 * about to be removed
8b67ad
 	 */
8b67ad
-	p = strchr(*f, ' ');
8b67ad
-	if (!p) {
8b67ad
-		/* Internal error, feature string inconsistent */
8b67ad
-		FREE(n);
8b67ad
-		return 1;
8b67ad
-	}
8b67ad
-	while (*p == ' ')
8b67ad
-		p++;
8b67ad
-	p--;
8b67ad
-	if (e != p) {
8b67ad
-		do {
8b67ad
-			e--;
8b67ad
-			d++;
8b67ad
-		} while (*e == ' ');
8b67ad
-		e++; d--;
8b67ad
-		strncat(n, p, (size_t)(e - p));
8b67ad
-		p += (size_t)(e - p);
8b67ad
-	}
8b67ad
+	strncat(n, e, (size_t)(p - e));
8b67ad
 	/* Skip feature to be removed */
8b67ad
 	p += d;
8b67ad
-
8b67ad
 	/* Copy remaining features */
8b67ad
-	if (strlen(p)) {
8b67ad
-		while (*p == ' ')
8b67ad
-			p++;
8b67ad
-		if (strlen(p)) {
8b67ad
-			p--;
8b67ad
-			strcat(n, p);
8b67ad
-		}
8b67ad
-	}
8b67ad
+	while (isspace(*p))
8b67ad
+		p++;
8b67ad
+	if (*p != '\0')
8b67ad
+		strcat(n, p);
8b67ad
+	else
8b67ad
+		strchop(n);
8b67ad
 
8b67ad
 out:
8b67ad
 	FREE(*f);