[dm-devel] [PATCH 3/4] libmultipath: add_feature: allow only 1 feature

Benjamin Marzinski bmarzins at redhat.com
Thu Sep 7 22:37:13 UTC 2017


On Thu, Sep 07, 2017 at 04:42:09PM -0500, Benjamin Marzinski wrote:
> On Tue, Aug 29, 2017 at 12:05:35AM +0200, Martin Wilck wrote:
> > The existing test "if feature is already present" doesn't work for
> > multiple features, and we are only using add_feature() for single
> > feature additions anyway. Simplify the code by not allowing spaces
> > in the feature string to be added. This way we can drop the
> > complex "count new features" code. Moreover, print an error message if
> > the existing features string is malformed.
> > 
> > The old code calculated the width of the feature count twice, and the
> > second time messed up the buffer length field passed to snprintf(); fix
> > that, too.  Finally, replace several strcat() invocations by one
> > strncpy() call to make the code easier to review.
> > 
> > Signed-off-by: Martin Wilck <mwilck at suse.com>
> > ---
> >  libmultipath/structs.c | 64 +++++++++++++++++---------------------------------
> >  1 file changed, 21 insertions(+), 43 deletions(-)
> > 
> > diff --git a/libmultipath/structs.c b/libmultipath/structs.c
> > index 11e33676..828e7907 100644
> > --- a/libmultipath/structs.c
> > +++ b/libmultipath/structs.c
> > @@ -516,8 +516,7 @@ void setup_feature(struct multipath *mpp, char *feature)
> >  int add_feature(char **f, const char *n)
> >  {
> >  	int c = 0, d, l;
> > -	char *e, *p, *t;
> > -	const char *q;
> > +	char *e, *t;
> >  
> >  	if (!f)
> >  		return 1;
> > @@ -526,6 +525,11 @@ int add_feature(char **f, const char *n)
> >  	if (!n || *n == '0')
> >  		return 0;
> >  
> > +	if (strchr(n, ' ') != NULL) {
> > +		condlog(0, "internal error: feature \"%s\" contains spaces", n);
> > +		return 1;
> > +	}
> > +
> >  	/* default feature is null */
> >  	if(!*f)
> >  	{
> > @@ -543,55 +547,29 @@ int add_feature(char **f, const char *n)
> >  
> >  	/* Get feature count */
> >  	c = strtoul(*f, &e, 10);
> > -	if (*f == e)
> > -		/* parse error */
> > +	if (*f == e || (*e != ' ' && *e != '\0')) {
> > +		condlog(0, "parse error in feature string \"%s\"", *f);
> >  		return 1;
> > -
> > -	/* Check if we need to increase feature count space */
> > -	l = strlen(*f) + strlen(n) + 1;
> > -
> > -	/* Count new features */
> > -	if ((c % 10) == 9)
> > -		l++;
> > -	c++;
> > -	q = n;
> > -	while (*q != '\0') {
> > -		if (*q == ' ' && q[1] != '\0' && q[1] != ' ') {
> > -			if ((c % 10) == 9)
> > -				l++;
> > -			c++;
> > -		}
> > -		q++;
> >  	}
> >  
> > +	/* Add 1 digit and 1 space */
> > +	l = strlen(e) + strlen(n) + 2;
> > +
> > +	c++;
> > +	/* Check if we need more digits for feature count */
> > +	for (d = c; d >= 10; d /= 10)
> > +		l++;
> > +
> >  	t = MALLOC(l + 1);
> >  	if (!t)
> >  		return 1;
> >  
> > -	memset(t, 0, l + 1);
> > +	/* e: old feature string with leading space, or "" */
> > +	if (*e == ' ')
> > +		while (*(e + 1) == ' ')
> > +			e++;
> >  
> > -	/* Update feature count */
> > -	d = c;
> > -	l = 1;
> > -	while (d > 9) {
> > -		d /= 10;
> > -		l++;
> > -	}
> > -	p = t;
> > -	snprintf(p, l + 2, "%0d ", c);
> > -
> > -	/* Copy the feature string */
> > -	p = strchr(*f, ' ');
> > -
> > -	if (p) {
> > -		while (*p == ' ')
> > -			p++;
> > -		strcat(t, p);
> > -		strcat(t, " ");
> > -	} else {
> > -		p = t + strlen(t);
> > -	}
> > -	strcat(t, n);
> > +	snprintf(t, l + 1, "%0d%s %s", c, e, n);
> 
> Just one nit, that I know I'm guilty of too (so Coverity says).  If
> you're sure that you have enough size for the string, you don't need
> snprintf. If you want to make sure that the string isn't too big, you
> should probably use "l" instead of "l + 1", so that you know that the
> string will get null termintated (from your earlier memset), and you
> won't read off the end of the array later. Otherwise, ACK. 

Nevermind, I was having a brain fart and thinking of strncpy.

-Ben

> 
> >  
> >  	FREE(*f);
> >  	*f = t;
> > -- 
> > 2.14.0
> 
> Reviewed-by: Benjamin Marzinski <bmarzins at redhat.com>
> 
> -Ben
> 
> --
> dm-devel mailing list
> dm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel




More information about the dm-devel mailing list