ash numeric overflow problem

Denys Vlasenko vda.linux at googlemail.com
Fri Jun 5 14:04:03 UTC 2009


On Fri, Jun 5, 2009 at 3:15 PM, Michael Abbott<michael at araneidae.co.uk> wrote:
> On Fri, 5 Jun 2009, Michael Abbott wrote:
>> I've just upgraded from 1.13.3 to 1.14.1, and there seem to be some
>> unpleasant numerical features.  First the serious breakage:
>>
>> 1.13.3:
>>       $ echo $((0x80000000))
>>       2147483648
>>
>> 1.14.1:
>>       $ echo $((0x80000000))
>>       2147483647
>>
>> Oops!  This is pretty worrying, actually.  I'll dig and try and figure
>> it out, but I think a heads up is in order.  Hopefully somebody who's
>> been working on the shell recently can point me where too look.
>
> Had to write this in a hurry.  Here's the case that really burnt me:
>
> 1.13.3:
>        $ echo $((0x80000000 & 1))
>        0
>
> 1.14.1:
>        $ echo $((0x80000000 & 1))
>        1
>        $ echo $((2147483648 & 1))
>        1
>
> Oh dear oh dear oh dear.

Looks like ash and bash act differently on arithmetic overflow.
bash treats "too big" numbers as 0:

# echo $((0x8000000000000000))
-9223372036854775808
# echo $((0x80000000000000000))
0

and ash as -1 (all-ones). It just uses strtol internally, and that's
what strtol returns.

Quick fix is to use CONFIG_SH_MATH_SUPPORT_64=y. Perhaps this is
what you inadvertently switched off (because option name
has changed in 1.14.x).


Complete fix is to add "errno = 0" and if() here in math.c:

                        errno = 0;
                        numstackptr->val = strto_arith_t(expr, (char
**) &expr, 0);
                        if (errno)
                                numstackptr->val = 0; /* bash compat */
                        goto num;

Does it work for you?
--
vda


More information about the busybox mailing list