]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix for SF bug #415514: "%#x" % 0 caused assertion failure/abort.
authorTim Peters <tim.peters@gmail.com>
Thu, 12 Apr 2001 00:35:51 +0000 (00:35 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 12 Apr 2001 00:35:51 +0000 (00:35 +0000)
http://sourceforge.net/tracker/index.php?func=detail&aid=415514&group_id=5470&atid=105470
For short ints, Python defers to the platform C library to figure out what
%#x should do.  The code asserted that the platform C returned a string
beginning with "0x".  However, that's not true when-- and only when --the
*value* being formatted is 0.  Changed the code to live with C's inconsistency
here.  In the meantime, the problem does not arise if you format a long 0 (0L)
instead.  However, that's because the code *we* wrote to do %#x conversions on
longs produces a leading "0x" regardless of value.  That's probably wrong too:
we should drop leading "0x", for consistency with C, when (& only when) formatting
0L.  So I changed the long formatting code to do that too.

Lib/test/test_format.py
Objects/stringobject.c
Objects/unicodeobject.c

index 6a6060384b924fbd82bd9b11e47f0ebbd497835d..ce5d5f2c80752ec5e721d63f49a33a129c4b74a9 100644 (file)
@@ -164,6 +164,22 @@ testboth("%d", 42, "42")
 testboth("%d", -42, "-42")
 testboth("%d", 42L, "42")
 testboth("%d", -42L, "-42")
+testboth("%#x", 1, "0x1")
+testboth("%#x", 1L, "0x1")
+testboth("%#X", 1, "0X1")
+testboth("%#X", 1L, "0X1")
+testboth("%#o", 1, "01")
+testboth("%#o", 1L, "01")
+testboth("%#o", 0, "0")
+testboth("%#o", 0L, "0")
+testboth("%o", 0, "0")
+testboth("%o", 0L, "0")
+testboth("%d", 0, "0")
+testboth("%d", 0L, "0")
+testboth("%#x", 0, "0")
+testboth("%#x", 0L, "0")
+testboth("%#X", 0, "0")
+testboth("%#X", 0L, "0")
 
 testboth("%x", 0x42, "42")
 # testboth("%x", -0x42, "ffffffbe") # Alas, that's specific to 32-bit machines
index 740cbe294e44ee6742092351d59c763fb303513b..8e1153693d0cd1e57747450aa58c7fc609d61a75 100644 (file)
@@ -2575,8 +2575,16 @@ _PyString_FormatLong(PyObject *val, int flags, int prec, int type,
        numdigits = len - numnondigits;
        assert(numdigits > 0);
 
-       /* Get rid of base marker unless F_ALT */
-       if ((flags & F_ALT) == 0) {
+       /* Get rid of base marker unless F_ALT.  Even if F_ALT, leading 0x
+        * must be stripped if the *value* is 0.
+        */
+       if ((flags & F_ALT) == 0 ||
+           ((flags & F_ALT) &&
+            (type == 'x' || type == 'X') &&
+            numdigits == 1 &&
+            !sign &&
+            buf[2] == '0'
+           )) {
                /* Need to skip 0x, 0X or 0. */
                int skipped = 0;
                switch (type) {
@@ -3015,17 +3023,21 @@ PyString_Format(PyObject *format, PyObject *args)
                                        width--;
                        }
                        if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
+                               /* There's a base marker ("0x" or "0X") if and
+                                * only if the value is non-zero.
+                                */
                                assert(pbuf[0] == '0');
-                               assert(pbuf[1] == c);
-                               if (fill != ' ') {
-                                       *res++ = *pbuf++;
-                                       *res++ = *pbuf++;
+                               if (pbuf[1] == c) {
+                                       if (fill != ' ') {
+                                               *res++ = *pbuf++;
+                                               *res++ = *pbuf++;
+                                       }
+                                       rescnt -= 2;
+                                       width -= 2;
+                                       if (width < 0)
+                                               width = 0;
+                                       len -= 2;
                                }
-                               rescnt -= 2;
-                               width -= 2;
-                               if (width < 0)
-                                       width = 0;
-                               len -= 2;
                        }
                        if (width > len && !(flags & F_LJUST)) {
                                do {
@@ -3037,9 +3049,8 @@ PyString_Format(PyObject *format, PyObject *args)
                                if (sign)
                                        *res++ = sign;
                                if ((flags & F_ALT) &&
-                                   (c == 'x' || c == 'X')) {
-                                       assert(pbuf[0] == '0');
-                                       assert(pbuf[1] == c);
+                                   (c == 'x' || c == 'X') &&
+                                   pbuf[1] == c) {
                                        *res++ = *pbuf++;
                                        *res++ = *pbuf++;
                                }
index c237789a79edfef77e4ecb224b24e7781dc2f263..aecc2618d1520b408dbcc83cacb25431721f2eec 100644 (file)
@@ -5081,16 +5081,17 @@ PyObject *PyUnicode_Format(PyObject *format,
            }
            if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
                assert(pbuf[0] == '0');
-               assert(pbuf[1] == c);
-               if (fill != ' ') {
-                   *res++ = *pbuf++;
-                   *res++ = *pbuf++;
+               if (pbuf[1] == c) {
+                       if (fill != ' ') {
+                           *res++ = *pbuf++;
+                           *res++ = *pbuf++;
+                       }
+                       rescnt -= 2;
+                       width -= 2;
+                       if (width < 0)
+                           width = 0;
+                       len -= 2;
                }
-               rescnt -= 2;
-               width -= 2;
-               if (width < 0)
-                   width = 0;
-               len -= 2;
            }
            if (width > len && !(flags & F_LJUST)) {
                do {
@@ -5101,9 +5102,9 @@ PyObject *PyUnicode_Format(PyObject *format,
            if (fill == ' ') {
                if (sign)
                    *res++ = sign;
-               if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
+               if ((flags & F_ALT) && (c == 'x' || c == 'X') &&
+                   pbuf[1] == c) {
                    assert(pbuf[0] == '0');
-                   assert(pbuf[1] == c);
                    *res++ = *pbuf++;
                    *res++ = *pbuf++;
                }