diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-10-07 10:35:48 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-10-07 10:35:48 (GMT) |
commit | 978b9d2a27fe0d787a21465e8728dab48ca57e83 (patch) | |
tree | 88b16cb20f7f5ebb1ec03a62a54eac1ae96a4bae | |
parent | db6c7f5c33ba4808907f227d5996ca70a67e21c6 (diff) | |
download | cpython-978b9d2a27fe0d787a21465e8728dab48ca57e83.zip cpython-978b9d2a27fe0d787a21465e8728dab48ca57e83.tar.gz cpython-978b9d2a27fe0d787a21465e8728dab48ca57e83.tar.bz2 |
Fix formatting memory consumption with very large padding specifications
-rw-r--r-- | Objects/unicodeobject.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 8608776..902dfe4 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12727,6 +12727,29 @@ formatchar(PyObject *v) return (Py_UCS4) -1; } +static int +repeat_accumulate(_PyAccu *acc, PyObject *obj, Py_ssize_t count) +{ + int r; + assert(count > 0); + assert(PyUnicode_Check(obj)); + if (count > 5) { + PyObject *repeated = unicode_repeat((PyUnicodeObject *) obj, count); + if (repeated == NULL) + return -1; + r = _PyAccu_Accumulate(acc, repeated); + Py_DECREF(repeated); + return r; + } + else { + do { + if (_PyAccu_Accumulate(acc, obj)) + return -1; + } while (--count); + return 0; + } +} + PyObject * PyUnicode_Format(PyObject *format, PyObject *args) { @@ -13145,10 +13168,9 @@ PyUnicode_Format(PyObject *format, PyObject *args) } if (width > len && !(flags & F_LJUST)) { assert(fillobj != NULL); - do { - if (_PyAccu_Accumulate(&acc, fillobj)) - goto onError; - } while (--width > len); + if (repeat_accumulate(&acc, fillobj, width - len)) + goto onError; + width = len; } if (fill == ' ') { if (sign) { @@ -13186,10 +13208,8 @@ PyUnicode_Format(PyObject *format, PyObject *args) Py_DECREF(v); if (r) goto onError; - while (--width >= len) { - if (_PyAccu_Accumulate(&acc, blank)) - goto onError; - } + if (width > len && repeat_accumulate(&acc, blank, width - len)) + goto onError; if (dict && (argidx < arglen) && c != '%') { PyErr_SetString(PyExc_TypeError, "not all arguments converted during string formatting"); |