[dm-devel] [PATCH 1/8] libmultipath: cleanup remove_feature
Benjamin Marzinski
bmarzins at redhat.com
Fri Oct 21 17:14:38 UTC 2022
On Thu, Oct 20, 2022 at 02:58:23PM +0000, Martin Wilck wrote:
> On Fri, 2022-10-07 at 12:35 -0500, Benjamin Marzinski wrote:
> > remove_feature() didn't correctly handle feature strings that used
> > whitespace other than spaces, which the kernel allows. It also didn't
> > check if the feature string to be removed was part of a larger
> > feature
> > token. Finally, it did a lot of unnecessary work. By failing if the
> > feature string to be removed contains leading or trailing whitespace,
> > the function can be significanly simplified.
> >
> > Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
>
> Reviewed-by: Martin Wilck <mwilck at suse.com>
>
> This is part of the code that always makes me think we should clean it
> up more thoroughly. Therefore I've added some remarks below.
>
> As you've started working on this, perhaps you want to follow up?
> If not, fine with me for now.
>
> Martin
>
> > ---
> > libmultipath/structs.c | 82 +++++++++++++++-------------------------
> > --
> > 1 file changed, 29 insertions(+), 53 deletions(-)
> >
> > diff --git a/libmultipath/structs.c b/libmultipath/structs.c
> > index 49621cb3..1f9945e0 100644
> > --- a/libmultipath/structs.c
> > +++ b/libmultipath/structs.c
> > @@ -6,6 +6,7 @@
> > #include <unistd.h>
> > #include <libdevmapper.h>
> > #include <libudev.h>
> > +#include <ctype.h>
> >
> > #include "checkers.h"
> > #include "vector.h"
> > @@ -663,7 +664,7 @@ int add_feature(char **f, const char *n)
> >
> > int remove_feature(char **f, const char *o)
> > {
> > - int c = 0, d, l;
> > + int c = 0, d;
> > char *e, *p, *n;
> > const char *q;
>
> I see you sticked to the conventions ;-) but the variable naming
> in this function could be improved.
Yeah. I didn't want to while I was chaning things, and then got lazy and
didn't do it in a separate patch, but these names certainly make harder
to follow the logic of the function. I send a patch that cleans this up.
> >
> > @@ -674,33 +675,35 @@ int remove_feature(char **f, const char *o)
> > if (!o || *o == '\0')
> > return 0;
> >
> > - /* Check if not present */
> > - if (!strstr(*f, o))
> > + d = strlen(o);
> > + if (isspace(*o) || isspace(*(o + d - 1))) {
> > + condlog(0, "internal error: feature \"%s\" has
> > leading or trailing spaces", o);
> > + return 1;
> > + }
> > +
> > + /* Check if present and not part of a larger feature token*/
> > + p = *f + 1; /* the size must be at the start of the features
> > string */
> > + while ((p = strstr(p, o)) != NULL) {
> > + if (isspace(*(p - 1)) &&
> > + (isspace(*(p + d)) || *(p + d) == '\0'))
> > + break;
> > + p += d;
> > + }
> > + if (!p)
> > return 0;
> >
> > /* Get feature count */
> > c = strtoul(*f, &e, 10);
> > - if (*f == e)
> > - /* parse error */
> > + if (*f == e || !isspace(*e)) {
> > + condlog(0, "parse error in feature string \"%s\"",
> > *f);
> > return 1;
> > -
> > - /* Normalize features */
> > - while (*o == ' ') {
> > - o++;
> > }
> > - /* Just spaces, return */
> > - if (*o == '\0')
> > - return 0;
> > - q = o + strlen(o);
> > - while (*q == ' ')
> > - q--;
> > - d = (int)(q - o);
> >
> > /* Update feature count */
> > c--;
> > q = o;
> > - while (q[0] != '\0') {
> > - if (q[0] == ' ' && q[1] != ' ' && q[1] != '\0')
> > + while (*q != '\0') {
> > + if (isspace(*q) && !isspace(*(q + 1)) && *(q + 1) !=
> > '\0')
> > c--;
> > q++;
> > }
> > @@ -714,15 +717,8 @@ int remove_feature(char **f, const char *o)
> > goto out;
> > }
> >
> > - /* Search feature to be removed */
> > - e = strstr(*f, o);
> > - if (!e)
> > - /* Not found, return */
> > - return 0;
> > -
> > /* Update feature count space */
> > - l = strlen(*f) - d;
> > - n = malloc(l + 1);
> > + n = malloc(strlen(*f) - d + 1);
>
> Given that this function never increases the length of the feature
> string, we might as well implement it without the allocating a new
> string.
A reason to do the malloc is so that we could free the larger chunk of
memory afterwards. But it's not like we're talking a significant
difference, so I'm fine will removing it for simplicity's sake.
-Ben
> > if (!n)
> > return 1;
> >
> > @@ -732,36 +728,16 @@ int remove_feature(char **f, const char *o)
> > * Copy existing features up to the feature
> > * about to be removed
> > */
> > - p = strchr(*f, ' ');
> > - if (!p) {
> > - /* Internal error, feature string inconsistent */
> > - free(n);
> > - return 1;
> > - }
> > - while (*p == ' ')
> > - p++;
> > - p--;
> > - if (e != p) {
> > - do {
> > - e--;
> > - d++;
> > - } while (*e == ' ');
> > - e++; d--;
> > - strncat(n, p, (size_t)(e - p));
> > - p += (size_t)(e - p);
> > - }
> > + strncat(n, e, (size_t)(p - e));
> > /* Skip feature to be removed */
> > p += d;
> > -
> > /* Copy remaining features */
> > - if (strlen(p)) {
> > - while (*p == ' ')
> > - p++;
> > - if (strlen(p)) {
> > - p--;
> > - strcat(n, p);
> > - }
> > - }
> > + while (isspace(*p))
> > + p++;
> > + if (*p != '\0')
> > + strcat(n, p);
> > + else
> > + strchop(n);
> >
> > out:
> > free(*f);
>
>
More information about the dm-devel
mailing list