Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d4e505

Browse files
committed
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
1 parent b9d1a4d commit 8d4e505

2 files changed

Lines changed: 34 additions & 37 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 3.1 alpha 0
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #4935: The overflow checking code in the expandtabs() method common
16+
to str, bytes and bytearray could be optimized away by the compiler, letting
17+
the interpreter segfault instead of raising an error.
18+
1519
- Issue #3720: Fix a crash when an iterator modifies its class and removes its
1620
__next__ method.
1721

Objects/stringlib/transmogrify.h

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,76 +22,69 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
2222
{
2323
const char *e, *p;
2424
char *q;
25-
Py_ssize_t i, j, old_j;
25+
size_t i, j;
2626
PyObject *u;
2727
int tabsize = 8;
28-
28+
2929
if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
30-
return NULL;
31-
30+
return NULL;
31+
3232
/* First pass: determine size of output string */
33-
i = j = old_j = 0;
33+
i = j = 0;
3434
e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
3535
for (p = STRINGLIB_STR(self); p < e; p++)
3636
if (*p == '\t') {
37-
if (tabsize > 0) {
38-
j += tabsize - (j % tabsize);
39-
/* XXX: this depends on a signed integer overflow to < 0 */
40-
/* C compilers, including gcc, do -NOT- guarantee this. */
41-
if (old_j > j) {
42-
PyErr_SetString(PyExc_OverflowError,
43-
"result is too long");
44-
return NULL;
45-
}
46-
old_j = j;
37+
if (tabsize > 0) {
38+
j += tabsize - (j % tabsize);
39+
if (j > PY_SSIZE_T_MAX) {
40+
PyErr_SetString(PyExc_OverflowError,
41+
"result is too long");
42+
return NULL;
43+
}
4744
}
48-
}
45+
}
4946
else {
5047
j++;
5148
if (*p == '\n' || *p == '\r') {
5249
i += j;
53-
old_j = j = 0;
54-
/* XXX: this depends on a signed integer overflow to < 0 */
55-
/* C compilers, including gcc, do -NOT- guarantee this. */
56-
if (i < 0) {
50+
j = 0;
51+
if (i > PY_SSIZE_T_MAX) {
5752
PyErr_SetString(PyExc_OverflowError,
5853
"result is too long");
5954
return NULL;
6055
}
6156
}
6257
}
63-
64-
if ((i + j) < 0) {
65-
/* XXX: this depends on a signed integer overflow to < 0 */
66-
/* C compilers, including gcc, do -NOT- guarantee this. */
58+
59+
if ((i + j) > PY_SSIZE_T_MAX) {
6760
PyErr_SetString(PyExc_OverflowError, "result is too long");
6861
return NULL;
6962
}
70-
63+
7164
/* Second pass: create output string and fill it */
7265
u = STRINGLIB_NEW(NULL, i + j);
7366
if (!u)
7467
return NULL;
75-
68+
7669
j = 0;
7770
q = STRINGLIB_STR(u);
78-
71+
7972
for (p = STRINGLIB_STR(self); p < e; p++)
8073
if (*p == '\t') {
81-
if (tabsize > 0) {
82-
i = tabsize - (j % tabsize);
83-
j += i;
84-
while (i--)
85-
*q++ = ' ';
86-
}
87-
}
88-
else {
74+
if (tabsize > 0) {
75+
i = tabsize - (j % tabsize);
76+
j += i;
77+
while (i--)
78+
*q++ = ' ';
79+
}
80+
}
81+
else {
8982
j++;
90-
*q++ = *p;
83+
*q++ = *p;
9184
if (*p == '\n' || *p == '\r')
9285
j = 0;
9386
}
94-
87+
9588
return u;
9689
}
9790

0 commit comments

Comments
 (0)