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
This commit is contained in:
parent
b9d1a4ddc3
commit
8d4e505aa8
|
@ -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,76 +22,69 @@ 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;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
|
if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
|
||||||
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,
|
|
||||||
"result is too long");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
old_j = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"result is too long");
|
"result is too long");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if ((i + j) < 0) {
|
j++;
|
||||||
/* XXX: this depends on a signed integer overflow to < 0 */
|
if (*p == '\n' || *p == '\r') {
|
||||||
/* C compilers, including gcc, do -NOT- guarantee this. */
|
i += j;
|
||||||
|
j = 0;
|
||||||
|
if (i > PY_SSIZE_T_MAX) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"result is too long");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i + j) > PY_SSIZE_T_MAX) {
|
||||||
PyErr_SetString(PyExc_OverflowError, "result is too long");
|
PyErr_SetString(PyExc_OverflowError, "result is too long");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second pass: create output string and fill it */
|
/* Second pass: create output string and fill it */
|
||||||
u = STRINGLIB_NEW(NULL, i + j);
|
u = STRINGLIB_NEW(NULL, i + j);
|
||||||
if (!u)
|
if (!u)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
q = STRINGLIB_STR(u);
|
q = STRINGLIB_STR(u);
|
||||||
|
|
||||||
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) {
|
||||||
i = tabsize - (j % tabsize);
|
i = tabsize - (j % tabsize);
|
||||||
j += i;
|
j += i;
|
||||||
while (i--)
|
while (i--)
|
||||||
*q++ = ' ';
|
*q++ = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
j++;
|
j++;
|
||||||
*q++ = *p;
|
*q++ = *p;
|
||||||
if (*p == '\n' || *p == '\r')
|
if (*p == '\n' || *p == '\r')
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue