From: Raymond Hettinger Date: Thu, 2 Jan 2003 22:08:39 +0000 (+0000) Subject: Backport MAL's patch for bug #659709: bogus computation of float length X-Git-Tag: v2.2.3c1~192 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=65b5e1fdbebe4ca35b665bc22bc51e9a806b4669;p=thirdparty%2FPython%2Fcpython.git Backport MAL's patch for bug #659709: bogus computation of float length --- diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py index cc61512a73e3..7537515941fe 100644 --- a/Lib/test/test_string.py +++ b/Lib/test/test_string.py @@ -55,3 +55,29 @@ string_tests.run_method_tests(test) 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 + diff --git a/Objects/stringobject.c b/Objects/stringobject.c index bd416bf1c7e2..3173f750c068 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -3059,21 +3059,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 = %#.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); } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index eb6f0d6c0ca9..18ab1459056a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5250,20 +5250,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 = %#.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 = %#.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); }