summaryrefslogtreecommitdiffstats
path: root/Objects/bytearrayobject.c
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2010-08-10 18:35:01 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2010-08-10 18:35:01 (GMT)
commitcf940c701f982d7a38144b31d09dc9613af841b7 (patch)
treeeb5368b6c9ab6fdf766c69fac3866a48c9c8a5cc /Objects/bytearrayobject.c
parent331ea92ade37e5dcf14c44df59e5eda2136b1a8f (diff)
downloadcpython-cf940c701f982d7a38144b31d09dc9613af841b7.zip
cpython-cf940c701f982d7a38144b31d09dc9613af841b7.tar.gz
cpython-cf940c701f982d7a38144b31d09dc9613af841b7.tar.bz2
Issue #9530: Fix undefined-behaviour-inducing overflow checks in bytes and bytearray implementations.
Diffstat (limited to 'Objects/bytearrayobject.c')
-rw-r--r--Objects/bytearrayobject.c54
1 files changed, 22 insertions, 32 deletions
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 33f80d5..cdc860f 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -310,9 +310,9 @@ bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count)
if (count < 0)
count = 0;
mysize = Py_SIZE(self);
- size = mysize * count;
- if (count != 0 && size / count != mysize)
+ if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
+ size = mysize * count;
result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
if (result != NULL && size != 0) {
if (mysize == 1)
@@ -335,9 +335,9 @@ bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count)
if (count < 0)
count = 0;
mysize = Py_SIZE(self);
- size = mysize * count;
- if (count != 0 && size / count != mysize)
+ if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
+ size = mysize * count;
if (size < self->ob_alloc) {
Py_SIZE(self) = size;
self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */
@@ -1505,30 +1505,28 @@ replace_interleave(PyByteArrayObject *self,
{
char *self_s, *result_s;
Py_ssize_t self_len, result_len;
- Py_ssize_t count, i, product;
+ Py_ssize_t count, i;
PyByteArrayObject *result;
self_len = PyByteArray_GET_SIZE(self);
- /* 1 at the end plus 1 after every character */
- count = self_len+1;
- if (maxcount < count)
+ /* 1 at the end plus 1 after every character;
+ count = min(maxcount, self_len + 1) */
+ if (maxcount <= self_len)
count = maxcount;
+ else
+ /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */
+ count = self_len + 1;
/* Check for overflow */
/* result_len = count * to_len + self_len; */
- product = count * to_len;
- if (product / to_len != count) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
- result_len = product + self_len;
- if (result_len < 0) {
+ assert(count > 0);
+ if (to_len > (PY_SSIZE_T_MAX - self_len) / count) {
PyErr_SetString(PyExc_OverflowError,
"replace string is too long");
return NULL;
}
+ result_len = count * to_len + self_len;
if (! (result = (PyByteArrayObject *)
PyByteArray_FromStringAndSize(NULL, result_len)) )
@@ -1758,7 +1756,7 @@ replace_single_character(PyByteArrayObject *self,
char *self_s, *result_s;
char *start, *next, *end;
Py_ssize_t self_len, result_len;
- Py_ssize_t count, product;
+ Py_ssize_t count;
PyByteArrayObject *result;
self_s = PyByteArray_AS_STRING(self);
@@ -1772,16 +1770,12 @@ replace_single_character(PyByteArrayObject *self,
/* use the difference between current and new, hence the "-1" */
/* result_len = self_len + count * (to_len-1) */
- product = count * (to_len-1);
- if (product / (to_len-1) != count) {
+ assert(count > 0);
+ if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) {
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
return NULL;
}
- result_len = self_len + product;
- if (result_len < 0) {
- PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
- return NULL;
- }
+ result_len = self_len + count * (to_len - 1);
if ( (result = (PyByteArrayObject *)
PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)
@@ -1825,7 +1819,7 @@ replace_substring(PyByteArrayObject *self,
char *self_s, *result_s;
char *start, *next, *end;
Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset, product;
+ Py_ssize_t count, offset;
PyByteArrayObject *result;
self_s = PyByteArray_AS_STRING(self);
@@ -1842,16 +1836,12 @@ replace_substring(PyByteArrayObject *self,
/* Check for overflow */
/* result_len = self_len + count * (to_len-from_len) */
- product = count * (to_len-from_len);
- if (product / (to_len-from_len) != count) {
- PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
- return NULL;
- }
- result_len = self_len + product;
- if (result_len < 0) {
+ assert(count > 0);
+ if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
return NULL;
}
+ result_len = self_len + count * (to_len - from_len);
if ( (result = (PyByteArrayObject *)
PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)