Forward-port of r52136,52138: a review of overflow-detecting code.
* unified the way intobject, longobject and mystrtoul handle
values around -sys.maxint-1.
* in general, trying to entierely avoid overflows in any computation
involving signed ints or longs is extremely involved. Fixed a few
simple cases where a compiler might be too clever (but that's all
guesswork).
* more overflow checks against bad data in marshal.c.
* 2.5 specific: fixed a number of places that were still confusing int
and Py_ssize_t. Some of them could potentially have caused
"real-world" breakage.
* list.pop(x): fixing overflow issues on x was messy. I just reverted
to PyArg_ParseTuple("n"), which does the right thing. (An obscure
test was trying to give a Decimal to list.pop()... doesn't make
sense any more IMHO)
* trying to write a few tests...
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 4c2faf4..aa2fd87 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -804,10 +804,22 @@
return ret;
}
if (flags & Py_PRINT_RAW) {
+ char *data = op->ob_sval;
+ Py_ssize_t size = op->ob_size;
+ while (size > INT_MAX) {
+ /* Very long strings cannot be written atomically.
+ * But don't write exactly INT_MAX bytes at a time
+ * to avoid memory aligment issues.
+ */
+ const int chunk_size = INT_MAX & ~0x3FFF;
+ fwrite(data, 1, chunk_size, fp);
+ data += chunk_size;
+ size -= chunk_size;
+ }
#ifdef __VMS
- if (op->ob_size) fwrite(op->ob_sval, (int) op->ob_size, 1, fp);
+ if (size) fwrite(data, (int)size, 1, fp);
#else
- fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
+ fwrite(data, 1, (int)size, fp);
#endif
return 0;
}
@@ -844,7 +856,7 @@
register PyStringObject* op = (PyStringObject*) obj;
size_t newsize = 2 + 4 * op->ob_size;
PyObject *v;
- if (newsize > PY_SSIZE_T_MAX) {
+ if (newsize > PY_SSIZE_T_MAX || newsize / 4 != op->ob_size) {
PyErr_SetString(PyExc_OverflowError,
"string is too large to make repr");
}
@@ -4237,7 +4249,7 @@
return NULL;
}
llen = PyString_Size(result);
- if (llen > PY_SSIZE_T_MAX) {
+ if (llen > INT_MAX) {
PyErr_SetString(PyExc_ValueError, "string too large in _PyString_FormatLong");
return NULL;
}
@@ -4726,9 +4738,10 @@
default:
PyErr_Format(PyExc_ValueError,
"unsupported format character '%c' (0x%x) "
- "at index %i",
+ "at index %zd",
c, c,
- (int)(fmt - 1 - PyString_AsString(format)));
+ (Py_ssize_t)(fmt - 1 -
+ PyString_AsString(format)));
goto error;
}
if (sign) {