[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