Re: [PATCH 1/2 v3] mkfs: unify numeric types of main variables in main()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 25, 2017 at 3:37 AM, Luis R. Rodriguez <mcgrof@xxxxxxxxxx> wrote:
> On Thu, Apr 20, 2017 at 03:58:39PM +0200, Jan Tulak wrote:
>> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
>> index 7a5c49f..40a32be 100644
>> --- a/mkfs/xfs_mkfs.c
>> +++ b/mkfs/xfs_mkfs.c
>> @@ -3431,17 +3431,17 @@ unknown(
>>       usage();
>>  }
>>
>> -long long
>> +uint64_t
>>  cvtnum(
>>       unsigned int    blksize,
>>       unsigned int    sectsize,
>>       const char      *s)
>>  {
>> -     long long       i;
>> +     uint64_t        i;
>>       char            *sp;
>>       int             c;
>>
>> -     i = strtoll(s, &sp, 0);
>> +     i = strtoull(s, &sp, 0);
>>       if (i == 0 && sp == s)
>>               return -1LL;
>>       if (*sp == '\0')
>
> I'm afraid this will not cut it, you see before we accepted negative values
> and used it as mechanism to catch errors, see the above return -1LL; with this
> change we'd only catch an error in parsing if the subopt's maxval happens to be
> smaller than -1LL which in turn will be returned as a positive value.
>
> Two more issues I spotted:
>
> a) the else condition on getnum() to use for when !sp->convert was left in your
> patch with strtoll() and I think you meant to convert that as well to
> strtoull()?
>
> b) I noted the existing cvtnum() code does not check for wrap arounds in its
> extra conversions.
>
> At first glance it may seem the best option is to modify the prototype of
> cvtnum() to return int to interpret errors, and have it set the uint64_t
> through a parameter pointer. The wrap around issue is orthogonal and would
> be an old issue, but such a change would help treat these as follows but
> as I will explain below this is perhaps not best for now.
>
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index ef40c9a36e40..5995245e471d 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1410,6 +1410,7 @@ getnum(
>  {
>         struct subopt_param     *sp = &opts->subopt_params[index];
>         uint64_t                c;
> +       int ret;
>
>         check_opt(opts, index, false);
>         set_conf_raw(opts->index, index, str);
> @@ -1434,13 +1435,16 @@ getnum(
>          * convert it ourselves to guarantee there is no trailing garbage in the
>          * number.
>          */
> -       if (sp->convert)
> -               c = cvtnum(get_conf_val(OPT_B, B_SIZE),
> -                          get_conf_val(OPT_D, D_SECTSIZE), str);
> -       else {
> +       if (sp->convert) {
> +               ret = cvtnum(get_conf_val(OPT_B, B_SIZE),
> +                            get_conf_val(OPT_D, D_SECTSIZE), str, &c);
> +               if (ret)
> +                       illegal_option(str, opts, index,
> +                                      _("Parse error, ret: %d", ret));

This printing won't work - we would have to use a sprintf, with all
the prealocation for the new string and so on. Or as I'm modifying it,
replace the if (ret) with a switch(ret) a print directly EINVAL/ERANGE
as part of the string.

> +       } else {
>                 char            *str_end;
>
> -               c = strtoll(str, &str_end, 0);
> +               c = strtoull(str, &str_end, 0);
>                 if (c == 0 && str_end == str)
>                         illegal_option(str, opts, index, NULL);
>                 if (*str_end != '\0')
> @@ -3814,24 +3818,25 @@ unknown(
>         usage();
>  }
>
> -uint64_t
> +int
>  cvtnum(
>         unsigned int    blksize,
>         unsigned int    sectsize,
> -       const char      *s)
> +       const char      *s,
> +       uint64_t *val)
>  {
>         uint64_t        i;
>         char            *sp;
>         int             c;
> +       uint64_t        orig_val;
>
>         i = strtoull(s, &sp, 0);
>         if (i == 0 && sp == s)
> -               return -1LL;
> +               return -EINVAL;
>         if (*sp == '\0')
> -               return i;
> -
> +               return -EINVAL;
This has to be *val = i; return 0;
Otherwise, we would report numbers without any suffix as an error. ;-)

>         if (sp[1] != '\0')
> -               return -1LL;
> +               return -EINVAL;
>
>         if (*sp == 'b') {
>                 if (!blksize) {
> @@ -3839,7 +3844,10 @@ cvtnum(
>  _("Blocksize must be provided prior to using 'b' suffix.\n"));
>                         usage();
>                 } else {
> -                       return i * blksize;
> +                       *val = i * blksize;
> +                       if (*val < i || *val < blksize)
> +                               return -ERANGE;
> +                       return 0;
>                 }
>         }
>         if (*sp == 's') {
> @@ -3848,11 +3856,15 @@ _("Blocksize must be provided prior to using 'b' suffix.\n"));
>  _("Sectorsize must be specified prior to using 's' suffix.\n"));
>                         usage();
>                 } else {
> -                       return i * sectsize;
> +                       *val = i * sectsize;
> +                       if (*val < i || *val < sectsize)
> +                               return -ERANGE;
> +                       return 0;
>                 }
>         }
>
>         c = tolower(*sp);
> +       orig_val = i;
>         switch (c) {
>         case 'e':
>                 i *= 1024LL;
> @@ -3870,11 +3882,14 @@ _("Sectorsize must be specified prior to using 's' suffix.\n"));
>                 i *= 1024LL;
>                 /* fall through */
>         case 'k':
> -               return i * 1024LL;
> +               *val = i * 1024LL;
> +               if (*val < orig_val)
> +                       return -ERANGE;
> +               return 0;
>         default:
>                 break;
>         }
> -       return -1LL;
> +       return -EINVAL;
>  }
>
>  static void __attribute__((noreturn))
>
> The issue with this of course is everyone and their mom calls cvtnum() and the
> amount of collateral for such type of change is significant for your patch series.
> One option may just be to bail on error within cvtnum() with a usage() call on
> error, as a temporary compromise, this way we only chug on *iff* the value was
> accepted and proper, and non-wrap-around, up to you.
>
>   Luis

Ehh, it is not really an issue.. cvtnum is called only on two places
in the whole xfsprogs. Changing mkfs/proto.c is just few lines added
to this patch and the changes in xfs_mkfs.c do cause few conflicts,
but it is nothing terrific, I rebased all my further changes in about
three minutes. I pushed it into the git tree, check it now...

And thanks for this patch for the patch. :-)

Jan

-- 
Jan Tulak
jtulak@xxxxxxxxxx / jan@xxxxxxxx
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux