]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-100637: Fix int and bool __sizeof__ calculation to include the 1 element ob_digit...
authorIonite <dev@ionite.io>
Mon, 2 Jan 2023 21:11:49 +0000 (05:11 +0800)
committerGitHub <noreply@github.com>
Mon, 2 Jan 2023 21:11:49 +0000 (21:11 +0000)
Fixes behaviour where int (and subtypes like bool) __sizeof__ under-reports true size as it did not take into account the size 1 `ob_digit` array for the zero int.

Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
Lib/test/test_sys.py
Misc/NEWS.d/next/Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst [new file with mode: 0644]
Objects/longobject.c

index 17a5026e2571e11709935e4500257b2297bee185..232b79971dc2b79ea8cf55e3f50dd73e1d844849 100644 (file)
@@ -1322,6 +1322,7 @@ class SizeofTest(unittest.TestCase):
         check = self.check_sizeof
         # bool
         check(True, vsize('') + self.longdigit)
+        check(False, vsize('') + self.longdigit)
         # buffer
         # XXX
         # builtin_function_or_method
@@ -1459,7 +1460,7 @@ class SizeofTest(unittest.TestCase):
         # listreverseiterator (list)
         check(reversed([]), size('nP'))
         # int
-        check(0, vsize(''))
+        check(0, vsize('') + self.longdigit)
         check(1, vsize('') + self.longdigit)
         check(-1, vsize('') + self.longdigit)
         PyLong_BASE = 2**sys.int_info.bits_per_digit
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst
new file mode 100644 (file)
index 0000000..164f6f5
--- /dev/null
@@ -0,0 +1 @@
+Fix :func:`int.__sizeof__` calculation to include the 1 element ob_digit array for 0 and False.
index 0df3b9a9d564e011d9a2485790974ec8bbc474a4..1db4ca418e066eca190512487973dde5743a9a5a 100644 (file)
@@ -5879,7 +5879,10 @@ int___sizeof___impl(PyObject *self)
 {
     Py_ssize_t res;
 
-    res = offsetof(PyLongObject, ob_digit) + Py_ABS(Py_SIZE(self))*sizeof(digit);
+    res = offsetof(PyLongObject, ob_digit)
+        /* using Py_MAX(..., 1) because we always allocate space for at least
+           one digit, even though the integer zero has a Py_SIZE of 0 */
+        + Py_MAX(Py_ABS(Py_SIZE(self)), 1)*sizeof(digit);
     return res;
 }