mirror of
https://github.com/python/cpython.git
synced 2025-11-01 06:01:29 +00:00
needforspeed: check for overflow in replace (from Andrew Dalke)
This commit is contained in:
parent
44aa9f7139
commit
0c71f88fc9
3 changed files with 54 additions and 15 deletions
|
|
@ -555,15 +555,14 @@ def test_replace(self):
|
|||
self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
|
||||
self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
|
||||
|
||||
### Commented out until the underlying libraries are fixed
|
||||
## def test_replace_overflow(self):
|
||||
## # Check for overflow checking on 32 bit machines
|
||||
## if sys.maxint != 2147483647:
|
||||
## return
|
||||
## A2_16 = "A" * (2**16)
|
||||
## self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
|
||||
## self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
|
||||
## self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
|
||||
def test_replace_overflow(self):
|
||||
# Check for overflow checking on 32 bit machines
|
||||
if sys.maxint != 2147483647:
|
||||
return
|
||||
A2_16 = "A" * (2**16)
|
||||
self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
|
||||
self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
|
||||
self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
|
||||
|
||||
def test_zfill(self):
|
||||
self.checkequal('123', '123', 'zfill', 2)
|
||||
|
|
|
|||
|
|
@ -2460,6 +2460,7 @@ mymemreplace(const char *str, Py_ssize_t len, /* input string */
|
|||
char *out_s;
|
||||
char *new_s;
|
||||
Py_ssize_t nfound, offset, new_len;
|
||||
Py_ssize_t product, delta;
|
||||
|
||||
if (len == 0 || (pat_len == 0 && sub_len == 0) || pat_len > len)
|
||||
goto return_same;
|
||||
|
|
@ -2473,7 +2474,24 @@ mymemreplace(const char *str, Py_ssize_t len, /* input string */
|
|||
if (nfound == 0)
|
||||
goto return_same;
|
||||
|
||||
new_len = len + nfound*(sub_len - pat_len);
|
||||
delta = (sub_len - pat_len);
|
||||
if (delta == 0) {
|
||||
new_len = len;
|
||||
} else {
|
||||
product = nfound * (sub_len - pat_len);
|
||||
if ((product / (sub_len - pat_len)) != nfound) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
return NULL;
|
||||
}
|
||||
new_len = len + product;
|
||||
if (new_len < 0) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_len == 0) {
|
||||
/* Have to allocate something for the caller to free(). */
|
||||
out_s = (char *)PyMem_MALLOC(1);
|
||||
|
|
@ -2578,7 +2596,8 @@ string_replace(PyStringObject *self, PyObject *args)
|
|||
|
||||
new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
|
||||
if (new_s == NULL) {
|
||||
PyErr_NoMemory();
|
||||
if (!PyErr_Occurred())
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
if (out_len == -1) {
|
||||
|
|
|
|||
|
|
@ -3866,9 +3866,11 @@ int PyUnicode_EncodeDecimal(Py_UNICODE *s,
|
|||
for some more background, see: http://effbot.org/stringlib */
|
||||
|
||||
/* note: fastsearch may access s[n], which isn't a problem when using
|
||||
Python's ordinary string types. also, the count mode returns -1 if
|
||||
there cannot possible be a match in the target string, and 0 if it
|
||||
has actually checked for matches. */
|
||||
Python's ordinary string types, but may cause problems if you're
|
||||
using this code in other contexts. also, the count mode returns -1
|
||||
if there cannot possible be a match in the target string, and 0 if
|
||||
it has actually checked for matches, but didn't find any. callers
|
||||
beware! */
|
||||
|
||||
#define FAST_COUNT 0
|
||||
#define FAST_SEARCH 1
|
||||
|
|
@ -4862,6 +4864,7 @@ PyObject *replace(PyUnicodeObject *self,
|
|||
} else {
|
||||
|
||||
Py_ssize_t n, i;
|
||||
Py_ssize_t product, new_size, delta;
|
||||
Py_UNICODE *p;
|
||||
|
||||
/* replace strings */
|
||||
|
|
@ -4870,7 +4873,25 @@ PyObject *replace(PyUnicodeObject *self,
|
|||
n = maxcount;
|
||||
if (n == 0)
|
||||
goto nothing;
|
||||
u = _PyUnicode_New(self->length + n * (str2->length - str1->length));
|
||||
/* new_size = self->length + n * (str2->length - str1->length)); */
|
||||
delta = (str2->length - str1->length);
|
||||
if (delta == 0) {
|
||||
new_size = self->length;
|
||||
} else {
|
||||
product = n * (str2->length - str1->length);
|
||||
if ((product / (str2->length - str1->length)) != n) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
return NULL;
|
||||
}
|
||||
new_size = self->length + product;
|
||||
if (new_size < 0) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
u = _PyUnicode_New(new_size);
|
||||
if (!u)
|
||||
return NULL;
|
||||
i = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue