]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Backport MAL's patch for bug #659709: bogus computation of float length
authorRaymond Hettinger <python@rcn.com>
Thu, 2 Jan 2003 22:08:39 +0000 (22:08 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 2 Jan 2003 22:08:39 +0000 (22:08 +0000)
Lib/test/test_string.py
Objects/stringobject.c
Objects/unicodeobject.c

index cc61512a73e355250903b9258794310e09395e30..7537515941fe25de5d41191d0a92f28b3155aaf3 100644 (file)
@@ -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
+    
index bd416bf1c7e23c3146f649ee325aab33fa1adab4..3173f750c0681391514074905bdb963d027d907e 100644 (file)
@@ -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 = %#.<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);
 }
index eb6f0d6c0ca96dbc3a104450c80a94095288331d..18ab1459056abce600faf904368ce4db2b0ab346 100644 (file)
@@ -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 = %#.<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);
 }