bug-gnu-utils
[Top][All Lists]
Advanced

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

Re: gawk number to string bug


From: Aharon Robbins
Subject: Re: gawk number to string bug
Date: Mon, 19 Dec 2005 05:39:25 +0200

Greetings.  Re this:

> Date: Wed, 14 Dec 2005 18:29:38 -0800
> From: David Ellsworth <address@hidden>
> Subject: gawk number to string bug
> To: address@hidden
> Cc: address@hidden
>
> I ran into a bug in how gawk converts numbers into strings.  
>
> Running the program
>   BEGIN { print 9223372036854775808 }
> prints
>   -9223372036854775808
> on a 64-bit machine.  On a 32-bit machine, the same program prints out
>   9.22337e+18
> which is correct.
>
> Note that 9223372036854775808 == 2^63.  Printing out other powers of 2
> is OK.
>
> Version details:
>   gawk version 3.1.5, freshly downloaded from gnu.org
>   gcc (GCC) 3.4.4 (Gentoo 3.4.4-r1, ssp-3.4.4-1.0, pie-8.7.8)
>   uname -a output:
>     Linux pixie 2.6.12-gentoo-r10 #2 SMP Tue Nov 1 03:42:22 PST 2005
>     x86_64 Dual Core AMD Opteron(tm) Processor 275 AuthenticAMD GNU/Linux
>
> (the 32-bit example used gawk version 3.1.3)
>
> - David

Thanks for the bug report. I was able to reproduce it on a 64-bit RHEL system.

The patch below fixes the problem. I may ultimately fix it differently; on
the test program I get different behaviors from the Bell Labs awk and from
mawk, so I haven't 100% decided how I want gawk to behave.

Thanks!

Arnold
---------------------------
--- node.c.save 2005-07-26 21:07:43.000000000 +0300
+++ node.c      2005-12-18 10:25:40.530448768 +0200
@@ -151,6 +151,7 @@
        register char *sp = buf;
        double val;
        char *orig, *trans, save;
+       register long num;
 
        if (! do_traditional && (s->flags & INTLSTR) != 0) {
                save = s->stptr[s->stlen];
@@ -163,9 +164,12 @@
                return tmp_string(trans, strlen(trans));
        }
 
-       /* not an integral value, or out of range */
-       if ((val = double_to_int(s->numbr)) != s->numbr
-           || val < LONG_MIN || val > LONG_MAX) {
+       /* conversion to long overflows, or out of range, or not integral */
+       val = double_to_int(s->numbr);
+       num = (long) val;
+       if (   (s->numbr > 0 && num < 0)
+           || (s->numbr < 0 && num > 0)
+           || val < LONG_MIN || val > LONG_MAX || val != s->numbr) {
                /*
                 * Once upon a time, if GFMT_WORKAROUND wasn't defined,
                 * we just blindly did this:
@@ -199,9 +203,7 @@
 
                goto no_malloc;
        } else {
-               /* integral value */
-               /* force conversion to long only once */
-               register long num = (long) val;
+               /* integral value, in range, too! */
                if (num < NVAL && num >= 0) {
                        sp = (char *) values[num];
                        s->stlen = 1;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]