[En-Nut-Discussion] error found in Nut/OS(4.10.3) C standard lib:strtol

jn m mjnbetter at gmail.com
Sun Jun 16 12:14:33 CEST 2013


the address of *strtol *is: http://www.ethernut.de/api/strtol_8c_source.html
please look at the code bellow in red color:

long strtol(CONST char *nptr, char **endptr, int base)
> {
>     register CONST char *s;
>     register long acc, cutoff;
>     register int c;
>     register int neg, any, cutlim;
>
>     s = nptr;
>     do {
>         c = (unsigned char) *s++;
>     } while (isspace(c));
>     if (c == '-') {
>         neg = 1;
>         c = *s++;
>     } else {
>         neg = 0;
>         if (c == '+')
>             c = *s++;
>     }
>     if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X'))
> {
>         c = s[1];
>         s += 2;
>         base = 16;
>     }
>     if (base == 0)
>         base = c == '0' ? 8 : 10;
>
>     cutoff = neg ? LONG_MIN : LONG_MAX;
>     cutlim = cutoff % base;
>     cutoff /= base;
>     if (neg) {
>         if (cutlim > 0) {
>             cutlim -= base;
>             cutoff += 1;
>         }
>         cutlim = -cutlim;
>     }
>     for (acc = 0, any = 0;; c = (unsigned char) *s++) {
>         if (isdigit(c))
>             c -= '0';
>         else if (isalpha(c))
>             c -= isupper(c) ? 'A' - 10 : 'a' - 10;
>         else
>             break;
>         if (c >= base)
>             break;
>         if (any < 0)
>             continue;
>         if (neg) {
>             if ((acc < cutoff || acc == cutoff) && c > cutlim) {
>                 any = -1;
>                 acc = LONG_MIN;
>                 errno = ERANGE;
>             } else {
>                 any = 1;
>                 acc *= base;
>                 acc -= c;
>             }
>         } else {
>             if ((acc > cutoff || acc == cutoff) && c > cutlim) {
>                 any = -1;
>                 acc = LONG_MAX;
>                 errno = ERANGE;
>             } else {
>                 any = 1;
>                 acc *= base;
>                 acc += c;
>             }
>         }
>     }
>     if (endptr != 0)
>         *endptr = (char *) (any ? s - 1 : nptr);
>     return (acc);
> }
>

if the pointer nptr point to a string "10522545454", the function strtol
will return value: 1932610862, though the expected result is: 2147483647
(test platform: ubuntu 10.04.1, gcc 4.4.3).
in the code:

>             if ((acc < cutoff || acc == cutoff) && c > cutlim) {
>
when acc < cutoff, c should not be compared with cutlim, 'cause it's
already overflow now.
I think it should be modified to:

>             if (acc > cutoff || (acc == cutoff && c > cutlim)) {
>
and wrong code:

>             if ((acc > cutoff || acc == cutoff) && c > cutlim) {
>
should be modified to:

>             if ((acc > cutoff || acc == cutoff) && c > cutlim) {
>
the modified codes have been tested by me:
*"10522545454": strtol return 2147483647
"-10522545454": strtol return -2147483648*

Hope this helps.
Best wishes!
I'm ma.jinig, from China, Nan Jing. 2013/06/16


More information about the En-Nut-Discussion mailing list