From 61adba0d65f416e3bf285b5881ce8705d1647f7b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 14 Jan 2023 17:01:49 +0000 Subject: [PATCH 1/2] gh-101037: Fix memory allocation for zeros of int subtypes --- .../2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst | 2 ++ Objects/longobject.c | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-14-17-03-08.gh-issue-101037.9ATNuf.rst 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); From 877067c181b2ee7714b83f4935f237f9df694e36 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 14 Jan 2023 17:42:54 +0000 Subject: [PATCH 2/2] Add note to longintrepr.h to clarify that ob_digit[0] is always safe to access. --- Include/cpython/longintrepr.h | 3 +++ 1 file changed, 3 insertions(+) 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.