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