summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2000-09-09 06:13:41 (GMT)
committerTim Peters <tim.peters@gmail.com>2000-09-09 06:13:41 (GMT)
commit8f422461b4c19b8a66beae218311917e688f03ce (patch)
treeb6a577d50d437b8e2d388f5892fcd1f645d2c84c
parent643d76d735726352dd40433b663d48617e27e200 (diff)
downloadcpython-8f422461b4c19b8a66beae218311917e688f03ce.zip
cpython-8f422461b4c19b8a66beae218311917e688f03ce.tar.gz
cpython-8f422461b4c19b8a66beae218311917e688f03ce.tar.bz2
Fix for bug 113934. string*n and unicode*n did no overflow checking at
all, either to see whether the # of chars fit in an int, or that the amount of memory needed fit in a size_t. Checking these is expensive, but the alternative is silently wrong answers (as in the bug report) or core dumps (which were easy to provoke using Unicode strings).
-rw-r--r--Objects/stringobject.c19
-rw-r--r--Objects/unicodeobject.c21
2 files changed, 36 insertions, 4 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index f7c3f4b..eee3551 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -393,16 +393,31 @@ string_repeat(register PyStringObject *a, register int n)
register int i;
register int size;
register PyStringObject *op;
+ size_t nbytes;
if (n < 0)
n = 0;
+ /* watch out for overflows: the size can overflow int,
+ * and the # of bytes needed can overflow size_t
+ */
size = a->ob_size * n;
+ if (n && size / n != a->ob_size) {
+ PyErr_SetString(PyExc_OverflowError,
+ "repeated string is too long");
+ return NULL;
+ }
if (size == a->ob_size) {
Py_INCREF(a);
return (PyObject *)a;
}
- /* PyObject_NewVar is inlined */
+ nbytes = size * sizeof(char);
+ if (nbytes / sizeof(char) != (size_t)size ||
+ nbytes + sizeof(PyStringObject) <= nbytes) {
+ PyErr_SetString(PyExc_OverflowError,
+ "repeated string is too long");
+ return NULL;
+ }
op = (PyStringObject *)
- PyObject_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
+ PyObject_MALLOC(sizeof(PyStringObject) + nbytes);
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 8ed6380..76bb92a 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3993,6 +3993,8 @@ unicode_repeat(PyUnicodeObject *str, int len)
{
PyUnicodeObject *u;
Py_UNICODE *p;
+ int nchars;
+ size_t nbytes;
if (len < 0)
len = 0;
@@ -4002,8 +4004,23 @@ unicode_repeat(PyUnicodeObject *str, int len)
Py_INCREF(str);
return (PyObject*) str;
}
-
- u = _PyUnicode_New(len * str->length);
+
+ /* ensure # of chars needed doesn't overflow int and # of bytes
+ * needed doesn't overflow size_t
+ */
+ nchars = len * str->length;
+ if (len && nchars / len != str->length) {
+ PyErr_SetString(PyExc_OverflowError,
+ "repeated string is too long");
+ return NULL;
+ }
+ nbytes = (nchars + 1) * sizeof(Py_UNICODE);
+ if (nbytes / sizeof(Py_UNICODE) != (size_t)(nchars + 1)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "repeated string is too long");
+ return NULL;
+ }
+ u = _PyUnicode_New(nchars);
if (!u)
return NULL;