summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-01-13 23:13:52 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-01-13 23:13:52 (GMT)
commitc2f02216b69b844e233a2bd86ba43508fee55c86 (patch)
tree9bb44dcd0f9f36f230b22d7e5ecf677ff2cf6228
parent3a5067c208dec1c702ae93aa26b03d5b0e7711ed (diff)
downloadcpython-c2f02216b69b844e233a2bd86ba43508fee55c86.zip
cpython-c2f02216b69b844e233a2bd86ba43508fee55c86.tar.gz
cpython-c2f02216b69b844e233a2bd86ba43508fee55c86.tar.bz2
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.
-rw-r--r--Misc/NEWS4
-rw-r--r--Objects/stringlib/transmogrify.h67
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;
}