[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: gawk crash with long floating-point numbers
From: |
Andrew J. Schorr |
Subject: |
Re: gawk crash with long floating-point numbers |
Date: |
Fri, 4 Nov 2005 09:07:05 -0500 |
User-agent: |
Mutt/1.4.1i |
On Thu, Nov 03, 2005 at 10:59:03PM +0000, Joseph S. Myers wrote:
> Running "gawk -f zex2 </dev/null" with the attached testcase script zex2
> yields a crash with gawk 3.1.5 on i686-pc-linux-gnu:
Interesting. It looks like the problem is in format_tree in this
code (line 1178):
(void) sprintf(obufout, cpbuf,
(int) fw, (int) prec, (double) tmpval);
The same problem exists in version 3.1.4. With a debugging statement
inserted before that sprintf, using your test case, we see that:
debug: fw = 0, prec = 6, tmpval = 1e+307, ofre = 511, cpbuf = %*.*f
debug: fw = 0, prec = 6, tmpval = 1e+307, ofre = 196, cpbuf = %*.*f
So when it goes to print the second (307-digit) float, there are only
196 remaining spaces in the output buffer, so it overflows.
The code above where it says:
chksize(fw + prec + 9); /* 9 == slop */
is supposed to protect against this, but fw seems to be 0 in this
case. So I guess the logic is not valid here.
There seem to be 2 possible ways of fixing this:
1. Try to fix the chksize call to have a proper estimate of the
length of the output to be printed.
2. Use snprintf to detect whether we need more space.
Option #2 seems easier, but I'm not sure whether there's some
reason to want to avoid that...
And by the way, doesn't the chksize macro have a bug?
Currently it says:
#define chksize(l) if ((l) > ofre) { \
size_t olen = obufout - obuf; \
erealloc(obuf, char *, osiz * 2, "format_tree"); \
obufout = obuf + olen; \
ofre += osiz; \
osiz *= 2; \
}
But how do we know that doubling the size of the
buffer will increase the size sufficiently? Shouldn't it
be something like this?
#define chksize(l) if ((l) > ofre) { \
size_t olen = obufout - obuf; \
size_t delta = osiz+l-ofre; \
erealloc(obuf, char *, osiz + delta, "format_tree"); \
obufout = obuf + olen; \
ofre += delta; \
osiz += delta; \
}
Possible patch attached.
Regards,
Andy
builtin.patch
Description: Text document