diff options
author | Guido van Rossum <guido@python.org> | 2008-03-11 21:18:06 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2008-03-11 21:18:06 (GMT) |
commit | 5bdff60617e6fc1d2e387a0b165cb23b82d7dae6 (patch) | |
tree | 36e95ad5eeac90c0bbac7ced507b4fa744e8d5fa /Objects/unicodeobject.c | |
parent | e8b4b605550441a17b8b2db3b9e3391b8752ce8d (diff) | |
download | cpython-5bdff60617e6fc1d2e387a0b165cb23b82d7dae6.zip cpython-5bdff60617e6fc1d2e387a0b165cb23b82d7dae6.tar.gz cpython-5bdff60617e6fc1d2e387a0b165cb23b82d7dae6.tar.bz2 |
Fix the overflows in expandtabs(). "This time for sure!"
(Exploit at request.)
Diffstat (limited to 'Objects/unicodeobject.c')
-rw-r--r-- | Objects/unicodeobject.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 0470ef4..0aed3ab 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -6495,7 +6495,8 @@ unicode_expandtabs(PyUnicodeObject *self, PyObject *args) Py_UNICODE *e; Py_UNICODE *p; Py_UNICODE *q; - Py_ssize_t i, j, old_j; + Py_UNICODE *qe; + Py_ssize_t i, j, incr; PyUnicodeObject *u; int tabsize = 8; @@ -6503,63 +6504,70 @@ unicode_expandtabs(PyUnicodeObject *self, PyObject *args) return NULL; /* First pass: determine size of output string */ - i = j = old_j = 0; - e = self->str + self->length; + i = 0; /* chars up to and including most recent \n or \r */ + j = 0; /* chars since most recent \n or \r (use in tab calculations) */ + e = self->str + self->length; /* end of input */ for (p = self->str; p < e; p++) if (*p == '\t') { 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; - } + incr = tabsize - (j % tabsize); /* cannot overflow */ + if (j > PY_SSIZE_T_MAX - incr) + goto overflow1; + j += incr; + } } else { + if (j > PY_SSIZE_T_MAX - 1) + goto overflow1; j++; if (*p == '\n' || *p == '\r') { + if (i > PY_SSIZE_T_MAX - j) + goto overflow1; i += j; - old_j = j = 0; - if (i < 0) { - PyErr_SetString(PyExc_OverflowError, - "new string is too long"); - return NULL; - } + j = 0; } } - if ((i + j) < 0) { - PyErr_SetString(PyExc_OverflowError, "new string is too long"); - return NULL; - } + if (i > PY_SSIZE_T_MAX - j) + goto overflow1; /* Second pass: create output string and fill it */ u = _PyUnicode_New(i + j); if (!u) return NULL; - j = 0; - q = u->str; + j = 0; /* same as in first pass */ + q = u->str; /* next output char */ + qe = u->str + u->length; /* end of output */ for (p = self->str; p < e; p++) if (*p == '\t') { if (tabsize > 0) { i = tabsize - (j % tabsize); j += i; - while (i--) + while (i--) { + if (q >= qe) + goto overflow2; *q++ = ' '; + } } } else { - j++; + if (q >= qe) + goto overflow2; *q++ = *p; + j++; if (*p == '\n' || *p == '\r') j = 0; } return (PyObject*) u; + + overflow2: + Py_DECREF(u); + overflow1: + PyErr_SetString(PyExc_OverflowError, "new string is too long"); + return NULL; } PyDoc_STRVAR(find__doc__, |