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