diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index 68dbf9c4382dc5..6d52427508b5fe 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -71,6 +71,9 @@ typedef long stwodigits; /* signed variant of twodigits */ 0 <= ob_digit[i] <= MASK. The allocation function takes care of allocating extra memory so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available. + We always allocate memory for at least one digit, so accessing ob_digit[0] + is always safe. However, in the case ob_size == 0, the contents of + ob_digit[0] may be undefined. CAUTION: Generic code manipulating subtypes of PyVarObject has to aware that ints abuse ob_size's sign bit. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst new file mode 100644 index 00000000000000..a48756657a29d3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst @@ -0,0 +1,2 @@ +Fix potential memory underallocation issue for instances of :class:`int` +subclasses with value zero. diff --git a/Objects/longobject.c b/Objects/longobject.c index 1db4ca418e066e..51ac86961c9954 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5638,6 +5638,11 @@ long_subtype_new(PyTypeObject *type, PyObject *x, PyObject *obase) n = Py_SIZE(tmp); if (n < 0) n = -n; + /* Fast operations for single digit integers (including zero) + * assume that there is always at least one digit present. */ + if (n == 0) { + n = 1; + } newobj = (PyLongObject *)type->tp_alloc(type, n); if (newobj == NULL) { Py_DECREF(tmp);