On Tue, Mar 27, 2018 at 10:48:51PM +0200, Tobias Stoeckmann wrote:
> On Tue, Mar 27, 2018 at 10:36:17PM +0200, Ingo Schwarze wrote:
> > > + int sig;
> > 
> > Drop this variable, it does no good but only harm.
> 
> Yeah, too bad that I didn't notice this left-over from a previous
> development step. Strange enough that regression tests didn't
> choke on it...
> 
> > > + /* skip leading zeros */
> > > + while (*p == '0' && isdigit((unsigned char)p[1]))
> > > +         p++;
> > > +
> > > + /* turn 0 always positive */
> > > + if (*p == '0' && !isdigit((unsigned char)p[1]))
> > > +         sig = 1;
> 
> As tb@ pointed out, the !isdigit check can be removed as well.
> 
> > > +         c = strncmp(p1, p2, len1);
> > 
> > That's another bug:
> > 
> >   schwarze@isnote $ /bin/test -1 -gt -2 ; echo $?
> >   1
> >   schwarze@isnote $ /bin/test 1 -gt 2 ; echo $?
> >   1
> 
> It's really great to have people who do extensive reviews. Thanks
> a lot for spotting this. I have added it to the regression tests.
> 
> > With these changes, OK schwarze@.  See below for the patch that
> > i tested.
> 
> Modified with tb@'s remark. Also I changed the error message
> "bad number" to "invalid", so we stay fully in sync with strtonum's
> error messages.
> 
> > Given that breaking test(1) might cause hard-to-find breakage
> > deep down in build systems and scripts, you might with a to
> > have a second OK for commit, though.
> 
> Definitely, I'm not out to rush this one in.

ok tb

> 
> 
> Index: bin/test/test.c
> ===================================================================
> RCS file: /cvs/src/bin/test/test.c,v
> retrieving revision 1.18
> diff -u -p -u -p -r1.18 test.c
> --- bin/test/test.c   24 Jul 2017 22:15:52 -0000      1.18
> +++ bin/test/test.c   27 Mar 2018 20:43:38 -0000
> @@ -16,6 +16,7 @@
>  #include <unistd.h>
>  #include <ctype.h>
>  #include <errno.h>
> +#include <limits.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -145,6 +146,8 @@ static int aexpr(enum token n);
>  static int nexpr(enum token n);
>  static int binop(void);
>  static int primary(enum token n);
> +static const char *getnstr(const char *, int *, size_t *);
> +static int intcmp(const char *, const char *);
>  static int filstat(char *nm, enum token mode);
>  static int getn(const char *s);
>  static int newerf(const char *, const char *);
> @@ -290,6 +293,70 @@ primary(enum token n)
>       return strlen(*t_wp) > 0;
>  }
>  
> +static const char *
> +getnstr(const char *s, int *signum, size_t *len)
> +{
> +     const char *p, *start;
> +
> +     /* skip leading whitespaces */
> +     p = s;
> +     while (isspace((unsigned char)*p))
> +             p++;
> +
> +     /* accept optional sign */
> +     if (*p == '-') {
> +             *signum = -1;
> +             p++;
> +     } else {
> +             *signum = 1;
> +             if (*p == '+')
> +                     p++;
> +     }
> +
> +     /* skip leading zeros */
> +     while (*p == '0' && isdigit((unsigned char)p[1]))
> +             p++;
> +
> +     /* turn 0 always positive */
> +     if (*p == '0')
> +             *signum = 1;
> +
> +     start = p;
> +     while (isdigit((unsigned char)*p))
> +             p++;
> +     *len = p - start;
> +
> +     /* allow trailing whitespaces */
> +     while (isspace((unsigned char)*p))
> +             p++;
> +
> +     /* validate number */
> +     if (*p != '\0' || *start == '\0')
> +             errx(2, "%s: invalid", s);
> +
> +     return start;
> +}
> +
> +static int
> +intcmp(const char *opnd1, const char *opnd2)
> +{
> +     const char *p1, *p2;
> +     size_t len1, len2;
> +     int c, sig1, sig2;
> +
> +     p1 = getnstr(opnd1, &sig1, &len1);
> +     p2 = getnstr(opnd2, &sig2, &len2);
> +
> +     if (sig1 != sig2)
> +             c = sig1;
> +     else if (len1 != len2)
> +             c = (len1 < len2) ? -sig1 : sig1;
> +     else
> +             c = strncmp(p1, p2, len1) * sig1;
> +
> +     return c;
> +}
> +
>  static int
>  binop(void)
>  {
> @@ -313,17 +380,17 @@ binop(void)
>       case STRGT:
>               return strcmp(opnd1, opnd2) > 0;
>       case INTEQ:
> -             return getn(opnd1) == getn(opnd2);
> +             return intcmp(opnd1, opnd2) == 0;
>       case INTNE:
> -             return getn(opnd1) != getn(opnd2);
> +             return intcmp(opnd1, opnd2) != 0;
>       case INTGE:
> -             return getn(opnd1) >= getn(opnd2);
> +             return intcmp(opnd1, opnd2) >= 0;
>       case INTGT:
> -             return getn(opnd1) > getn(opnd2);
> +             return intcmp(opnd1, opnd2) > 0;
>       case INTLE:
> -             return getn(opnd1) <= getn(opnd2);
> +             return intcmp(opnd1, opnd2) <= 0;
>       case INTLT:
> -             return getn(opnd1) < getn(opnd2);
> +             return intcmp(opnd1, opnd2) < 0;
>       case FILNT:
>               return newerf(opnd1, opnd2);
>       case FILOT:
> @@ -455,22 +522,26 @@ t_lex(char *s)
>  static int
>  getn(const char *s)
>  {
> -     char *p;
> -     long r;
> -
> -     errno = 0;
> -     r = strtol(s, &p, 10);
> -
> -     if (errno != 0)
> -             errx(2, "%s: out of range", s);
> -
> -     while (isspace((unsigned char)*p))
> -             p++;
> +     char buf[32];
> +     const char *errstr, *p;
> +     size_t len;
> +     int r, sig;
> +
> +     p = getnstr(s, &sig, &len);
> +     if (sig != 1)
> +             errstr = "too small";
> +     else if (len >= sizeof(buf))
> +             errstr = "too large";
> +     else {
> +             strlcpy(buf, p, sizeof(buf));
> +             buf[len] = '\0';
> +             r = strtonum(buf, 0, INT_MAX, &errstr);
> +     }
>  
> -     if (*p)
> -             errx(2, "%s: bad number", s);
> +     if (errstr != NULL)
> +             errx(2, "%s: %s", s, errstr);
>  
> -     return (int) r;
> +     return r;
>  }
>  
>  static int
> Index: regress/bin/test/TEST.sh
> ===================================================================
> RCS file: /cvs/src/regress/bin/test/TEST.sh,v
> retrieving revision 1.2
> diff -u -p -u -p -r1.2 TEST.sh
> --- regress/bin/test/TEST.sh  25 Nov 2014 23:09:22 -0000      1.2
> +++ regress/bin/test/TEST.sh  27 Mar 2018 20:43:38 -0000
> @@ -124,6 +124,17 @@ t 0 '0 -eq 0'
>  t 1 '-5 -eq 5'
>  t 0 '\( 0 -eq 0 \)'
>  t 1 '1 -eq 0 -o a = a -a 1 -eq 0 -o a = aa'
> +t 0 '" +123 " -eq 123'
> +t 1 '"-123  " -gt " -1"'
> +t 0 '123 -gt -123'
> +t 0 '-0 -eq +0'
> +t 1 '+0 -gt 0'
> +t 0 '0 -eq 0'
> +t 0 '0000 -eq -0'
> +t 0 '-1 -gt -2'
> +t 1 '1 -gt 2'
> +t 1 '4294967296 -eq 0'
> +t 0 '12345678901234567890 -eq +0012345678901234567890'
>  
>  t 1 '"" -o ""'
>  t 1 '"" -a ""'
> 

Reply via email to