From c2f02216b69b844e233a2bd86ba43508fee55c86 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 13 Jan 2009 23:13:52 +0000 Subject: Issue #4935: The overflow checking code in the expandtabs() method common to str, bytes and bytearray could be optimized away by the compiler, letting the interpreter segfault instead of raising an error. --- Misc/NEWS | 4 +++ Objects/stringlib/transmogrify.h | 67 ++++++++++++++++++---------------------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index e39fe8a..f9122bb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- Issue #4935: The overflow checking code in the expandtabs() method common + to str, bytes and bytearray could be optimized away by the compiler, letting + the interpreter segfault instead of raising an error. + - Issue #3720: Fix a crash when an iterator modifies its class and removes its __next__ method. diff --git a/Objects/stringlib/transmogrify.h b/Objects/stringlib/transmogrify.h index fe478c3..7dc8177 100644 --- a/Objects/stringlib/transmogrify.h +++ b/Objects/stringlib/transmogrify.h @@ -22,76 +22,69 @@ stringlib_expandtabs(PyObject *self, PyObject *args) { const char *e, *p; char *q; - Py_ssize_t i, j, old_j; + size_t i, j; PyObject *u; int tabsize = 8; - + if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize)) - return NULL; - + return NULL; + /* First pass: determine size of output string */ - i = j = old_j = 0; + i = j = 0; e = STRINGLIB_STR(self) + STRINGLIB_LEN(self); for (p = STRINGLIB_STR(self); p < e; p++) if (*p == '\t') { - if (tabsize > 0) { - j += tabsize - (j % tabsize); - /* XXX: this depends on a signed integer overflow to < 0 */ - /* C compilers, including gcc, do -NOT- guarantee this. */ - if (old_j > j) { - PyErr_SetString(PyExc_OverflowError, - "result is too long"); - return NULL; - } - old_j = j; + if (tabsize > 0) { + j += tabsize - (j % tabsize); + if (j > PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, + "result is too long"); + return NULL; + } } - } + } else { j++; if (*p == '\n' || *p == '\r') { i += j; - old_j = j = 0; - /* XXX: this depends on a signed integer overflow to < 0 */ - /* C compilers, including gcc, do -NOT- guarantee this. */ - if (i < 0) { + j = 0; + if (i > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "result is too long"); return NULL; } } } - - if ((i + j) < 0) { - /* XXX: this depends on a signed integer overflow to < 0 */ - /* C compilers, including gcc, do -NOT- guarantee this. */ + + if ((i + j) > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "result is too long"); return NULL; } - + /* Second pass: create output string and fill it */ u = STRINGLIB_NEW(NULL, i + j); if (!u) return NULL; - + j = 0; q = STRINGLIB_STR(u); - + for (p = STRINGLIB_STR(self); p < e; p++) if (*p == '\t') { - if (tabsize > 0) { - i = tabsize - (j % tabsize); - j += i; - while (i--) - *q++ = ' '; - } - } - else { + if (tabsize > 0) { + i = tabsize - (j % tabsize); + j += i; + while (i--) + *q++ = ' '; + } + } + else { j++; - *q++ = *p; + *q++ = *p; if (*p == '\n' || *p == '\r') j = 0; } - + return u; } -- cgit v0.12