From d7e7f79ca7c2029e46a06d21a7a5abea631b5d13 Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 3 Jan 2023 05:11:49 +0800 Subject: gh-100637: Fix int and bool __sizeof__ calculation to include the 1 element ob_digit array for 0 and False (#100663) 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 --- Lib/test/test_sys.py | 3 ++- .../Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst | 1 + Objects/longobject.c | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 17a5026..232b799 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -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 index 0000000..164f6f5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-01-15-59-48.gh-issue-100637.M2n6Kg.rst @@ -0,0 +1 @@ +Fix :func:`int.__sizeof__` calculation to include the 1 element ob_digit array for 0 and False. diff --git a/Objects/longobject.c b/Objects/longobject.c index 0df3b9a..1db4ca4 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -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; } -- cgit v0.12