Commit 15862429 authored by Antoine Pitrou's avatar Antoine Pitrou

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.

(*) or at least it is our interpretation
parent e8be798e
...@@ -12,6 +12,10 @@ What's New in Python 3.1 alpha 0 ...@@ -12,6 +12,10 @@ What's New in Python 3.1 alpha 0
Core and Builtins 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 - Issue #3720: Fix a crash when an iterator modifies its class and removes its
__next__ method. __next__ method.
......
...@@ -22,7 +22,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args) ...@@ -22,7 +22,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
{ {
const char *e, *p; const char *e, *p;
char *q; char *q;
Py_ssize_t i, j, old_j; size_t i, j;
PyObject *u; PyObject *u;
int tabsize = 8; int tabsize = 8;
...@@ -30,30 +30,25 @@ stringlib_expandtabs(PyObject *self, PyObject *args) ...@@ -30,30 +30,25 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
return NULL; return NULL;
/* First pass: determine size of output string */ /* First pass: determine size of output string */
i = j = old_j = 0; i = j = 0;
e = STRINGLIB_STR(self) + STRINGLIB_LEN(self); e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
for (p = STRINGLIB_STR(self); p < e; p++) for (p = STRINGLIB_STR(self); p < e; p++)
if (*p == '\t') { if (*p == '\t') {
if (tabsize > 0) { if (tabsize > 0) {
j += tabsize - (j % tabsize); j += tabsize - (j % tabsize);
/* XXX: this depends on a signed integer overflow to < 0 */ if (j > PY_SSIZE_T_MAX) {
/* C compilers, including gcc, do -NOT- guarantee this. */
if (old_j > j) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"result is too long"); "result is too long");
return NULL; return NULL;
} }
old_j = j;
} }
} }
else { else {
j++; j++;
if (*p == '\n' || *p == '\r') { if (*p == '\n' || *p == '\r') {
i += j; i += j;
old_j = j = 0; j = 0;
/* XXX: this depends on a signed integer overflow to < 0 */ if (i > PY_SSIZE_T_MAX) {
/* C compilers, including gcc, do -NOT- guarantee this. */
if (i < 0) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"result is too long"); "result is too long");
return NULL; return NULL;
...@@ -61,9 +56,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args) ...@@ -61,9 +56,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
} }
} }
if ((i + j) < 0) { if ((i + j) > PY_SSIZE_T_MAX) {
/* XXX: this depends on a signed integer overflow to < 0 */
/* C compilers, including gcc, do -NOT- guarantee this. */
PyErr_SetString(PyExc_OverflowError, "result is too long"); PyErr_SetString(PyExc_OverflowError, "result is too long");
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment