Merge in release25-maint r60793:
Added checks for integer overflows, contributed by Google. Some are
only available if asserts are left in the code, in cases where they
can't be triggered from Python code.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index a2ebb4a..e18eb2a 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -2792,11 +2792,43 @@
PyString_AS_STRING(item)[0];
} else {
/* do we need more space? */
- Py_ssize_t need = j + reslen + len-i-1;
+ Py_ssize_t need = j;
+
+ /* calculate space requirements while checking for overflow */
+ if (need > PY_SSIZE_T_MAX - reslen) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need += reslen;
+
+ if (need > PY_SSIZE_T_MAX - len) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need += len;
+
+ if (need <= i) {
+ Py_DECREF(item);
+ goto Fail_1;
+ }
+
+ need = need - i - 1;
+
+ assert(need >= 0);
+ assert(outlen >= 0);
+
if (need > outlen) {
/* overallocate, to avoid reallocations */
- if (need<2*outlen)
+ if (outlen > PY_SSIZE_T_MAX / 2) {
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ if (need<2*outlen) {
need = 2*outlen;
+ }
if (_PyString_Resize(&result, need)) {
Py_DECREF(item);
return NULL;
@@ -2888,11 +2920,31 @@
else {
/* do we need more space? */
Py_ssize_t need = j + reslen + len - i - 1;
+
+ /* check that didnt overflow */
+ if ((j > PY_SSIZE_T_MAX - reslen) ||
+ ((j + reslen) > PY_SSIZE_T_MAX - len) ||
+ ((j + reslen + len) < i) ||
+ ((j + reslen + len - i) <= 0)) {
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ assert(need >= 0);
+ assert(outlen >= 0);
+
if (need > outlen) {
/* overallocate,
to avoid reallocations */
- if (need < 2 * outlen)
- need = 2 * outlen;
+ if (need < 2 * outlen) {
+ if (outlen > PY_SSIZE_T_MAX / 2) {
+ Py_DECREF(item);
+ return NULL;
+ } else {
+ need = 2 * outlen;
+ }
+ }
+
if (PyUnicode_Resize(
&result, need) < 0) {
Py_DECREF(item);