summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-04-12 00:35:51 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-04-12 00:35:51 (GMT)
commit711088d9b8c6898aad571fb251cb40a8b7d42f64 (patch)
tree937822a57e2984b35b9720c9b67fa0f0e0d213f0 /Objects
parent4642cb9ac9636dec1e939a75f5da3fc263b51326 (diff)
downloadcpython-711088d9b8c6898aad571fb251cb40a8b7d42f64.zip
cpython-711088d9b8c6898aad571fb251cb40a8b7d42f64.tar.gz
cpython-711088d9b8c6898aad571fb251cb40a8b7d42f64.tar.bz2
Fix for SF bug #415514: "%#x" % 0 caused assertion failure/abort.
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.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/stringobject.c39
-rw-r--r--Objects/unicodeobject.c23
2 files changed, 37 insertions, 25 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 740cbe2..8e11536 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -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++;
}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index c237789..aecc261 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -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++;
}