diff options
Diffstat (limited to 'Objects/stringobject.c')
-rw-r--r-- | Objects/stringobject.c | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 92bc95bf37..62955b9c7a 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -3265,7 +3265,7 @@ string_expandtabs(PyStringObject *self, PyObject *args) { const char *e, *p; char *q; - Py_ssize_t i, j; + Py_ssize_t i, j, old_j; PyObject *u; int tabsize = 8; @@ -3273,21 +3273,38 @@ string_expandtabs(PyStringObject *self, PyObject *args) return NULL; /* First pass: determine size of output string */ - i = j = 0; + i = j = old_j = 0; e = PyString_AS_STRING(self) + PyString_GET_SIZE(self); for (p = PyString_AS_STRING(self); p < e; p++) if (*p == '\t') { - if (tabsize > 0) + if (tabsize > 0) { j += tabsize - (j % tabsize); + if (old_j > j) { + PyErr_SetString(PyExc_OverflowError, + "new string is too long"); + return NULL; + } + old_j = j; + } } else { j++; if (*p == '\n' || *p == '\r') { i += j; - j = 0; + old_j = j = 0; + if (i < 0) { + PyErr_SetString(PyExc_OverflowError, + "new string is too long"); + return NULL; + } } } + if ((i + j) < 0) { + PyErr_SetString(PyExc_OverflowError, "new string is too long"); + return NULL; + } + /* Second pass: create output string and fill it */ u = PyString_FromStringAndSize(NULL, i + j); if (!u) @@ -4199,12 +4216,13 @@ _PyString_FormatLong(PyObject *val, int flags, int prec, int type, result = val->ob_type->tp_str(val); break; case 'o': - result = val->ob_type->tp_as_number->nb_oct(val); + numnondigits = 2; + result = PyNumber_ToBase(val, 8); break; case 'x': case 'X': numnondigits = 2; - result = val->ob_type->tp_as_number->nb_hex(val); + result = PyNumber_ToBase(val, 16); break; default: assert(!"'type' not in [duoxX]"); @@ -4239,32 +4257,16 @@ _PyString_FormatLong(PyObject *val, int flags, int prec, int type, assert(numdigits > 0); /* Get rid of base marker unless F_ALT */ - if ((flags & F_ALT) == 0) { - /* Need to skip 0x, 0X or 0. */ - int skipped = 0; - switch (type) { - case 'o': - assert(buf[sign] == '0'); - /* If 0 is only digit, leave it alone. */ - if (numdigits > 1) { - skipped = 1; - --numdigits; - } - break; - case 'x': - case 'X': - assert(buf[sign] == '0'); - assert(buf[sign + 1] == 'x'); - skipped = 2; - numnondigits -= 2; - break; - } - if (skipped) { - buf += skipped; - len -= skipped; - if (sign) - buf[0] = '-'; - } + if (((flags & F_ALT) == 0 && + (type == 'o' || type == 'x' || type == 'X'))) { + assert(buf[sign] == '0'); + assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' || + buf[sign+1] == 'o'); + numnondigits -= 2; + buf += 2; + len -= 2; + if (sign) + buf[0] = '-'; assert(len == numnondigits + numdigits); assert(numdigits > 0); } @@ -4333,9 +4335,10 @@ formatint(char *buf, size_t buflen, int flags, prec = 1; if ((flags & F_ALT) && - (type == 'x' || type == 'X')) { - /* When converting under %#x or %#X, there are a number + (type == 'x' || type == 'X' || type == 'o')) { + /* When converting under %#o, %#x or %#X, there are a number * of issues that cause pain: + * - for %#o, we want a different base marker than C * - when 0 is being converted, the C standard leaves off * the '0x' or '0X', which is inconsistent with other * %#x/%#X conversions and inconsistent with Python's @@ -4363,7 +4366,7 @@ formatint(char *buf, size_t buflen, int flags, prec, type); } - /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal)) + /* buf = '+'/'-'/'' + '0o'/'0x'/'' + '[0-9]'*max(prec, len(x in octal)) * worst case buf = '-0x' + [0-9]*prec, where prec >= 11 */ if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) { @@ -4751,7 +4754,8 @@ PyString_Format(PyObject *format, PyObject *args) if (width > len) width--; } - if ((flags & F_ALT) && (c == 'x' || c == 'X')) { + if ((flags & F_ALT) && + (c == 'x' || c == 'X' || c == 'o')) { assert(pbuf[0] == '0'); assert(pbuf[1] == c); if (fill != ' ') { @@ -4774,7 +4778,7 @@ PyString_Format(PyObject *format, PyObject *args) if (sign) *res++ = sign; if ((flags & F_ALT) && - (c == 'x' || c == 'X')) { + (c == 'x' || c == 'X' || c == 'o')) { assert(pbuf[0] == '0'); assert(pbuf[1] == c); *res++ = *pbuf++; |