mirror of
https://github.com/python/cpython
synced 2024-09-23 01:23:46 +00:00
Patch for bug #659709: bogus computation of float length
Python 2.2.x backport candidate. (This bug has been around since Python 1.6.)
This commit is contained in:
parent
bbfb910416
commit
79f57833f3
|
@ -57,3 +57,29 @@ def __repr__(self):
|
|||
string.whitespace
|
||||
string.lowercase
|
||||
string.uppercase
|
||||
|
||||
# Float formatting
|
||||
for prec in range(100):
|
||||
formatstring = u'%%.%if' % prec
|
||||
value = 0.01
|
||||
for x in range(60):
|
||||
value = value * 3.141592655 / 3.0 * 10.0
|
||||
#print 'Overflow check for x=%i and prec=%i:' % \
|
||||
# (x, prec),
|
||||
try:
|
||||
result = formatstring % value
|
||||
except OverflowError:
|
||||
# The formatfloat() code in stringobject.c and
|
||||
# unicodeobject.c uses a 120 byte buffer and switches from
|
||||
# 'f' formatting to 'g' at precision 50, so we expect
|
||||
# OverflowErrors for the ranges x < 50 and prec >= 67.
|
||||
if x >= 50 or \
|
||||
prec < 67:
|
||||
print '*** unexpected OverflowError for x=%i and prec=%i' % (x, prec)
|
||||
else:
|
||||
#print 'OverflowError'
|
||||
pass
|
||||
else:
|
||||
#print result
|
||||
pass
|
||||
|
||||
|
|
|
@ -476,6 +476,31 @@ def test_fixup(s):
|
|||
else:
|
||||
print '*** formatting u"%%c" %% %i should give a ValueError' % ordinal
|
||||
|
||||
# float formatting
|
||||
for prec in range(100):
|
||||
formatstring = u'%%.%if' % prec
|
||||
value = 0.01
|
||||
for x in range(60):
|
||||
value = value * 3.141592655 / 3.0 * 10.0
|
||||
#print 'Overflow check for x=%i and prec=%i:' % \
|
||||
# (x, prec),
|
||||
try:
|
||||
result = formatstring % value
|
||||
except OverflowError:
|
||||
# The formatfloat() code in stringobject.c and
|
||||
# unicodeobject.c uses a 120 byte buffer and switches from
|
||||
# 'f' formatting to 'g' at precision 50, so we expect
|
||||
# OverflowErrors for the ranges x < 50 and prec >= 67.
|
||||
if x >= 50 or \
|
||||
prec < 67:
|
||||
print '*** unexpected OverflowError for x=%i and prec=%i' % (x, prec)
|
||||
else:
|
||||
#print 'OverflowError'
|
||||
pass
|
||||
else:
|
||||
#print result
|
||||
pass
|
||||
|
||||
# formatting jobs delegated from the string implementation:
|
||||
verify('...%(foo)s...' % {'foo':u"abc"} == u'...abc...')
|
||||
verify('...%(foo)s...' % {'foo':"abc"} == '...abc...')
|
||||
|
|
|
@ -3361,21 +3361,31 @@ formatfloat(char *buf, size_t buflen, int flags,
|
|||
prec = 6;
|
||||
if (type == 'f' && fabs(x)/1e25 >= 1e25)
|
||||
type = 'g';
|
||||
PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
|
||||
(flags&F_ALT) ? "#" : "",
|
||||
prec, type);
|
||||
/* worst case length calc to ensure no buffer overrun:
|
||||
/* Worst case length calc to ensure no buffer overrun:
|
||||
|
||||
'g' formats:
|
||||
fmt = %#.<prec>g
|
||||
buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
|
||||
for any double rep.)
|
||||
len = 1 + prec + 1 + 2 + 5 = 9 + prec
|
||||
|
||||
'f' formats:
|
||||
buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50)
|
||||
len = 1 + 50 + 1 + prec = 52 + prec
|
||||
|
||||
If prec=0 the effective precision is 1 (the leading digit is
|
||||
always given), therefore increase by one to 10+prec. */
|
||||
if (buflen <= (size_t)10 + (size_t)prec) {
|
||||
always given), therefore increase the length by one.
|
||||
|
||||
*/
|
||||
if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) ||
|
||||
(type == 'f' && buflen <= (size_t)53 + (size_t)prec)) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"formatted float is too long (precision too large?)");
|
||||
return -1;
|
||||
}
|
||||
PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
|
||||
(flags&F_ALT) ? "#" : "",
|
||||
prec, type);
|
||||
PyOS_snprintf(buf, buflen, fmt, x);
|
||||
return strlen(buf);
|
||||
}
|
||||
|
|
|
@ -5999,20 +5999,31 @@ formatfloat(Py_UNICODE *buf,
|
|||
prec = 6;
|
||||
if (type == 'f' && (fabs(x) / 1e25) >= 1e25)
|
||||
type = 'g';
|
||||
PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
|
||||
(flags & F_ALT) ? "#" : "", prec, type);
|
||||
/* worst case length calc to ensure no buffer overrun:
|
||||
fmt = %#.<prec>g
|
||||
buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
|
||||
for any double rep.)
|
||||
len = 1 + prec + 1 + 2 + 5 = 9 + prec
|
||||
/* Worst case length calc to ensure no buffer overrun:
|
||||
|
||||
'g' formats:
|
||||
fmt = %#.<prec>g
|
||||
buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
|
||||
for any double rep.)
|
||||
len = 1 + prec + 1 + 2 + 5 = 9 + prec
|
||||
|
||||
'f' formats:
|
||||
buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50)
|
||||
len = 1 + 50 + 1 + prec = 52 + prec
|
||||
|
||||
If prec=0 the effective precision is 1 (the leading digit is
|
||||
always given), therefore increase by one to 10+prec. */
|
||||
if (buflen <= (size_t)10 + (size_t)prec) {
|
||||
always given), therefore increase the length by one.
|
||||
|
||||
*/
|
||||
if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) ||
|
||||
(type == 'f' && buflen <= (size_t)53 + (size_t)prec)) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"formatted float is too long (precision too long?)");
|
||||
"formatted float is too long (precision too large?)");
|
||||
return -1;
|
||||
}
|
||||
PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
|
||||
(flags&F_ALT) ? "#" : "",
|
||||
prec, type);
|
||||
return usprintf(buf, fmt, x);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue