[dm-devel] [PATCH 07/21] libmultipath: use strbuf in parse_vpd_pg83()

Martin Wilck mwilck at suse.com
Tue Nov 30 11:26:47 UTC 2021


On Mon, 2021-11-29 at 19:18 -0600, Benjamin Marzinski wrote:
> On Fri, Nov 19, 2021 at 12:13:24AM +0100, mwilck at suse.com wrote:
> > From: Martin Wilck <mwilck at suse.com>
> > 
> > By using the strbuf API, the code gets more readable, as we need
> > less output size checks.
> > 
> > While at it, avoid a possible crash by passing a NULL pointer
> > to memchr().
> > 
> > Signed-off-by: Martin Wilck <mwilck at suse.com>
> > ---
> >  libmultipath/discovery.c | 113 +++++++++++++++++------------------
> > ----
> >  1 file changed, 49 insertions(+), 64 deletions(-)
> > 
> > diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
> > index 5ce9031..16b6fae 100644
> > --- a/libmultipath/discovery.c
> > +++ b/libmultipath/discovery.c
> > @@ -1120,6 +1120,7 @@ parse_vpd_pg83(const unsigned char *in,
> > size_t in_len,
> >         size_t len, vpd_len, i;
> >         int vpd_type, prio = -1;
> >         int err = -ENODATA;
> > +       STRBUF_ON_STACK(buf);
> >  
> >          /* Need space at least for one digit */
> >         if (out_len <= 1)
> > @@ -1237,92 +1238,76 @@ parse_vpd_pg83(const unsigned char *in,
> > size_t in_len,
> >         if (vpd_type == 0x2 || vpd_type == 0x3) {
> >                 size_t i;
> >  
> > -               len = sprintf(out, "%d", vpd_type);
> > -               if (2 * vpd_len >= out_len - len) {
> > -                       condlog(1, "%s: WWID overflow, type %d,
> > %zu/%zu bytes required",
> > -                               __func__, vpd_type,
> > -                               2 * vpd_len + len + 1, out_len);
> > -                       vpd_len = (out_len - len - 1) / 2;
> > -               }
> > +               if ((err = print_strbuf(&buf, "%d", vpd_type)) < 0)
> > +                       return err;
> >                 for (i = 0; i < vpd_len; i++)
> > -                       len += sprintf(out + len,
> > -                                      "%02x", vpd[i]);
> > +                       if ((err = print_strbuf(&buf, "%02x",
> > vpd[i])) < 0)
> > +                               return err;
> >         } else if (vpd_type == 0x8) {
> > -               if (!memcmp("eui.", vpd, 4))
> > -                       out[0] =  '2';
> > +               char type;
> > +
> > +                if (!memcmp("eui.", vpd, 4))
> > +                       type =  '2';
> >                 else if (!memcmp("naa.", vpd, 4))
> > -                       out[0] = '3';
> > +                       type = '3';
> >                 else
> > -                       out[0] = '8';
> > +                       type = '8';
> > +               if ((err = fill_strbuf(&buf, type, 1)) < 0)
> > +                       return err;
> >  
> >                 vpd += 4;
> >                 len = vpd_len - 4;
> > -               while (len > 2 && vpd[len - 2] == '\0')
> > -                       --len;
> > -               if (len > out_len - 1) {
> > -                       condlog(1, "%s: WWID overflow, type 8/%c,
> > %zu/%zu bytes required",
> > -                               __func__, out[0], len + 1,
> > out_len);
> > -                       len = out_len - 1;
> > +               if ((err = __append_strbuf_str(&buf, (const char
> > *)vpd, len)) < 0)
> > +                       return err;
> > +
> > +                /* The input is 0-padded, make sure the length is
> > correct */
> > +               truncate_strbuf(&buf,
> > strlen(get_strbuf_str(&buf)));
> > +               len = get_strbuf_len(&buf);
> > +               if (type != '8') {
> > +                       char *buffer = __get_strbuf_buf(&buf);
> > +
> > +                       for (i = 0; i < len; ++i)
> > +                               buffer[i] = tolower(buffer[i]);
> >                 }
> >  
> > -               if (out[0] == '8')
> > -                       for (i = 0; i < len; ++i)
> > -                               out[1 + i] = vpd[i];
> > -               else
> > -                       for (i = 0; i < len; ++i)
> > -                               out[1 + i] = tolower(vpd[i]);
> > -
> > -               /* designator should be 0-terminated, but let's
> > make sure */
> > -               out[len] = '\0';
> > -
> >         } else if (vpd_type == 0x1) {
> >                 const unsigned char *p;
> >                 size_t p_len;
> >  
> > -               out[0] = '1';
> > -               len = 1;
> > -               while ((p = memchr(vpd, ' ', vpd_len))) {
> > +               if ((err = fill_strbuf(&buf, '1', 1)) < 0)
> > +                       return err;
> > +               while (vpd && (p = memchr(vpd, ' ', vpd_len))) {
> 
> vpd should never be zero here unless it wraps around, which seems
> very
> unlikely.  Is this just to make coverity happy, or do you mean
> (*vpd)?
> 

Coverity likes arguments for memchr() to be NULL-checked beforehand, 
but that wasn't the main reason.

See below, there's "vpd = p". And p can (and will sooner or later) be
NULL, because memchr() returns NULL if it doesn't find anything.


> -Ben
> 
> >                         p_len = p - vpd;
> > -                       if (len + p_len > out_len - 1) {
> > -                               condlog(1, "%s: WWID overflow, type
> > 1, %zu/%zu bytes required",
> > -                                       __func__, len + p_len,
> > out_len);
> > -                               p_len = out_len - len - 1;
> > -                       }
> > -                       memcpy(out + len, vpd, p_len);
> > -                       len += p_len;
> > -                       if (len >= out_len - 1) {
> > -                               out[len] = '\0';
> > -                               break;
> > -                       }
> > -                       out[len] = '_';
> > -                       len ++;
> > -                       if (len >= out_len - 1) {
> > -                               out[len] = '\0';
> > -                               break;
> > -                       }
> > +                       if ((err = __append_strbuf_str(&buf, (const
> > char *)vpd,
> > +                                                      p_len)) < 0)
> > +                               return err;
> >                         vpd = p;

Here.

Regards,
Martin






More information about the dm-devel mailing list