From 85dd6cb6df996b1197266d1a50ecc9187a91e481 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@python.org>
Date: Wed, 30 Nov 2022 17:22:52 +0100
Subject: [PATCH] gh-99845: Use size_t type in __sizeof__() methods (#99846)

The implementation of __sizeof__() methods using _PyObject_SIZE() now
use an unsigned type (size_t) to compute the size, rather than a signed
type (Py_ssize_t).

Cast explicitly signed (Py_ssize_t) values to unsigned type
(Py_ssize_t).
---
 Modules/_collectionsmodule.c    | 12 +++++-------
 Modules/_decimal/_decimal.c     |  8 +++-----
 Modules/_elementtree.c          | 13 +++++++------
 Modules/_io/bufferedio.c        | 11 +++++------
 Modules/_io/bytesio.c           | 10 ++++------
 Modules/_pickle.c               | 27 ++++++++++++--------------
 Modules/_struct.c               | 10 ++++------
 Modules/arraymodule.c           |  6 +++---
 Modules/clinic/_elementtree.c.h | 10 +++++-----
 Modules/clinic/_pickle.c.h      | 18 ++++++++---------
 Modules/itertoolsmodule.c       | 34 +++++++++++++--------------------
 Modules/mmapmodule.c            |  9 ++++-----
 Objects/bytearrayobject.c       |  7 +++----
 Objects/listobject.c            |  7 +++----
 Objects/setobject.c             | 11 +++++------
 15 files changed, 85 insertions(+), 108 deletions(-)

diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index 5fa58382188..68131f3b54d 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1508,15 +1508,13 @@ deque_init(dequeobject *deque, PyObject *args, PyObject *kwdargs)
 static PyObject *
 deque_sizeof(dequeobject *deque, void *unused)
 {
-    Py_ssize_t res;
-    Py_ssize_t blocks;
-
-    res = _PyObject_SIZE(Py_TYPE(deque));
+    size_t res = _PyObject_SIZE(Py_TYPE(deque));
+    size_t blocks;
     blocks = (size_t)(deque->leftindex + Py_SIZE(deque) + BLOCKLEN - 1) / BLOCKLEN;
-    assert(deque->leftindex + Py_SIZE(deque) - 1 ==
-           (blocks - 1) * BLOCKLEN + deque->rightindex);
+    assert(((size_t)deque->leftindex + (size_t)Py_SIZE(deque) - 1) ==
+           ((blocks - 1) * BLOCKLEN + (size_t)deque->rightindex));
     res += blocks * sizeof(block);
-    return PyLong_FromSsize_t(res);
+    return PyLong_FromSize_t(res);
 }
 
 PyDoc_STRVAR(sizeof_doc,
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index 2d6e4e4d62b..bc97615ffb4 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -4796,13 +4796,11 @@ dec_reduce(PyObject *self, PyObject *dummy UNUSED)
 static PyObject *
 dec_sizeof(PyObject *v, PyObject *dummy UNUSED)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(v));
+    size_t res = _PyObject_SIZE(Py_TYPE(v));
     if (mpd_isdynamic_data(MPD(v))) {
-        res += MPD(v)->alloc * sizeof(mpd_uint_t);
+        res += (size_t)MPD(v)->alloc * sizeof(mpd_uint_t);
     }
-    return PyLong_FromSsize_t(res);
+    return PyLong_FromSize_t(res);
 }
 
 /* __trunc__ */
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 0c68ede42ca..555c22f88b3 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -876,19 +876,20 @@ deepcopy(PyObject *object, PyObject *memo)
 
 
 /*[clinic input]
-_elementtree.Element.__sizeof__ -> Py_ssize_t
+_elementtree.Element.__sizeof__ -> size_t
 
 [clinic start generated code]*/
 
-static Py_ssize_t
+static size_t
 _elementtree_Element___sizeof___impl(ElementObject *self)
-/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
+/*[clinic end generated code: output=baae4e7ae9fe04ec input=54e298c501f3e0d0]*/
 {
-    Py_ssize_t result = _PyObject_SIZE(Py_TYPE(self));
+    size_t result = _PyObject_SIZE(Py_TYPE(self));
     if (self->extra) {
         result += sizeof(ElementObjectExtra);
-        if (self->extra->children != self->extra->_children)
-            result += sizeof(PyObject*) * self->extra->allocated;
+        if (self->extra->children != self->extra->_children) {
+            result += (size_t)self->extra->allocated * sizeof(PyObject*);
+        }
     }
     return result;
 }
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index e2610931caa..6df55b5b830 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -389,12 +389,11 @@ buffered_dealloc(buffered *self)
 static PyObject *
 buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self));
-    if (self->buffer)
-        res += self->buffer_size;
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
+    if (self->buffer) {
+        res += (size_t)self->buffer_size;
+    }
+    return PyLong_FromSize_t(res);
 }
 
 static int
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 41be3497506..6698c60355f 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -957,17 +957,15 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
 static PyObject *
 bytesio_sizeof(bytesio *self, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self));
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
     if (self->buf && !SHARED_BUF(self)) {
-        Py_ssize_t s = _PySys_GetSizeOf(self->buf);
-        if (s == -1) {
+        size_t s = _PySys_GetSizeOf(self->buf);
+        if (s == (size_t)-1) {
             return NULL;
         }
         res += s;
     }
-    return PyLong_FromSsize_t(res);
+    return PyLong_FromSize_t(res);
 }
 
 static int
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 2078779663a..1b34977806b 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -4575,26 +4575,25 @@ _pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
 
 /*[clinic input]
 
-_pickle.Pickler.__sizeof__ -> Py_ssize_t
+_pickle.Pickler.__sizeof__ -> size_t
 
 Returns size in memory, in bytes.
 [clinic start generated code]*/
 
-static Py_ssize_t
+static size_t
 _pickle_Pickler___sizeof___impl(PicklerObject *self)
-/*[clinic end generated code: output=106edb3123f332e1 input=8cbbec9bd5540d42]*/
+/*[clinic end generated code: output=23ad75658d3b59ff input=d8127c8e7012ebd7]*/
 {
-    Py_ssize_t res, s;
-
-    res = _PyObject_SIZE(Py_TYPE(self));
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
     if (self->memo != NULL) {
         res += sizeof(PyMemoTable);
         res += self->memo->mt_allocated * sizeof(PyMemoEntry);
     }
     if (self->output_buffer != NULL) {
-        s = _PySys_GetSizeOf(self->output_buffer);
-        if (s == -1)
+        size_t s = _PySys_GetSizeOf(self->output_buffer);
+        if (s == (size_t)-1) {
             return -1;
+        }
         res += s;
     }
     return res;
@@ -7079,22 +7078,20 @@ _pickle_Unpickler_find_class_impl(UnpicklerObject *self,
 
 /*[clinic input]
 
-_pickle.Unpickler.__sizeof__ -> Py_ssize_t
+_pickle.Unpickler.__sizeof__ -> size_t
 
 Returns size in memory, in bytes.
 [clinic start generated code]*/
 
-static Py_ssize_t
+static size_t
 _pickle_Unpickler___sizeof___impl(UnpicklerObject *self)
-/*[clinic end generated code: output=119d9d03ad4c7651 input=13333471fdeedf5e]*/
+/*[clinic end generated code: output=4648d84c228196df input=27180b2b6b524012]*/
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self));
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
     if (self->memo != NULL)
         res += self->memo_size * sizeof(PyObject *);
     if (self->marks != NULL)
-        res += self->marks_size * sizeof(Py_ssize_t);
+        res += (size_t)self->marks_size * sizeof(Py_ssize_t);
     if (self->input_line != NULL)
         res += strlen(self->input_line) + 1;
     if (self->encoding != NULL)
diff --git a/Modules/_struct.c b/Modules/_struct.c
index c960b81b246..0cf34fbf9a3 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -2090,13 +2090,11 @@ PyDoc_STRVAR(s_sizeof__doc__,
 static PyObject *
 s_sizeof(PyStructObject *self, void *unused)
 {
-    Py_ssize_t size;
-    formatcode *code;
-
-    size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
-    for (code = self->s_codes; code->fmtdef != NULL; code++)
+    size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
+    for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) {
         size += sizeof(formatcode);
-    return PyLong_FromSsize_t(size);
+    }
+    return PyLong_FromSize_t(size);
 }
 
 /* List of functions */
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index dcf510e9788..114c69a0335 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -1773,9 +1773,9 @@ static PyObject *
 array_array___sizeof___impl(arrayobject *self)
 /*[clinic end generated code: output=d8e1c61ebbe3eaed input=805586565bf2b3c6]*/
 {
-    Py_ssize_t res;
-    res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * self->ob_descr->itemsize;
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
+    res += (size_t)self->allocated * (size_t)self->ob_descr->itemsize;
+    return PyLong_FromSize_t(res);
 }
 
 
diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h
index 0a2a74e220c..33ccaf7e7c7 100644
--- a/Modules/clinic/_elementtree.c.h
+++ b/Modules/clinic/_elementtree.c.h
@@ -106,20 +106,20 @@ PyDoc_STRVAR(_elementtree_Element___sizeof____doc__,
 #define _ELEMENTTREE_ELEMENT___SIZEOF___METHODDEF    \
     {"__sizeof__", (PyCFunction)_elementtree_Element___sizeof__, METH_NOARGS, _elementtree_Element___sizeof____doc__},
 
-static Py_ssize_t
+static size_t
 _elementtree_Element___sizeof___impl(ElementObject *self);
 
 static PyObject *
 _elementtree_Element___sizeof__(ElementObject *self, PyObject *Py_UNUSED(ignored))
 {
     PyObject *return_value = NULL;
-    Py_ssize_t _return_value;
+    size_t _return_value;
 
     _return_value = _elementtree_Element___sizeof___impl(self);
-    if ((_return_value == -1) && PyErr_Occurred()) {
+    if ((_return_value == (size_t)-1) && PyErr_Occurred()) {
         goto exit;
     }
-    return_value = PyLong_FromSsize_t(_return_value);
+    return_value = PyLong_FromSize_t(_return_value);
 
 exit:
     return return_value;
@@ -1105,4 +1105,4 @@ skip_optional:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=67a80531eaf43815 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4ad006cadce01571 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h
index e9ff2604719..adb3abc5eb2 100644
--- a/Modules/clinic/_pickle.c.h
+++ b/Modules/clinic/_pickle.c.h
@@ -49,20 +49,20 @@ PyDoc_STRVAR(_pickle_Pickler___sizeof____doc__,
 #define _PICKLE_PICKLER___SIZEOF___METHODDEF    \
     {"__sizeof__", (PyCFunction)_pickle_Pickler___sizeof__, METH_NOARGS, _pickle_Pickler___sizeof____doc__},
 
-static Py_ssize_t
+static size_t
 _pickle_Pickler___sizeof___impl(PicklerObject *self);
 
 static PyObject *
 _pickle_Pickler___sizeof__(PicklerObject *self, PyObject *Py_UNUSED(ignored))
 {
     PyObject *return_value = NULL;
-    Py_ssize_t _return_value;
+    size_t _return_value;
 
     _return_value = _pickle_Pickler___sizeof___impl(self);
-    if ((_return_value == -1) && PyErr_Occurred()) {
+    if ((_return_value == (size_t)-1) && PyErr_Occurred()) {
         goto exit;
     }
-    return_value = PyLong_FromSsize_t(_return_value);
+    return_value = PyLong_FromSize_t(_return_value);
 
 exit:
     return return_value;
@@ -301,20 +301,20 @@ PyDoc_STRVAR(_pickle_Unpickler___sizeof____doc__,
 #define _PICKLE_UNPICKLER___SIZEOF___METHODDEF    \
     {"__sizeof__", (PyCFunction)_pickle_Unpickler___sizeof__, METH_NOARGS, _pickle_Unpickler___sizeof____doc__},
 
-static Py_ssize_t
+static size_t
 _pickle_Unpickler___sizeof___impl(UnpicklerObject *self);
 
 static PyObject *
 _pickle_Unpickler___sizeof__(UnpicklerObject *self, PyObject *Py_UNUSED(ignored))
 {
     PyObject *return_value = NULL;
-    Py_ssize_t _return_value;
+    size_t _return_value;
 
     _return_value = _pickle_Unpickler___sizeof___impl(self);
-    if ((_return_value == -1) && PyErr_Occurred()) {
+    if ((_return_value == (size_t)-1) && PyErr_Occurred()) {
         goto exit;
     }
-    return_value = PyLong_FromSsize_t(_return_value);
+    return_value = PyLong_FromSize_t(_return_value);
 
 exit:
     return return_value;
@@ -980,4 +980,4 @@ skip_optional_kwonly:
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=3321309c2157ee74 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=730dc26938561313 input=a9049054013a1b77]*/
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 4b0a4d88c43..e8b9bc76eec 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -2484,11 +2484,9 @@ product_dealloc(productobject *lz)
 static PyObject *
 product_sizeof(productobject *lz, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(lz));
-    res += PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(lz));
+    res += (size_t)PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
+    return PyLong_FromSize_t(res);
 }
 
 PyDoc_STRVAR(sizeof_doc, "Returns size in memory, in bytes.");
@@ -2817,11 +2815,9 @@ combinations_dealloc(combinationsobject *co)
 static PyObject *
 combinations_sizeof(combinationsobject *co, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(co));
-    res += co->r * sizeof(Py_ssize_t);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(co));
+    res += (size_t)co->r * sizeof(Py_ssize_t);
+    return PyLong_FromSize_t(res);
 }
 
 static int
@@ -3153,11 +3149,9 @@ cwr_dealloc(cwrobject *co)
 static PyObject *
 cwr_sizeof(cwrobject *co, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(co));
-    res += co->r * sizeof(Py_ssize_t);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(co));
+    res += (size_t)co->r * sizeof(Py_ssize_t);
+    return PyLong_FromSize_t(res);
 }
 
 static int
@@ -3498,12 +3492,10 @@ permutations_dealloc(permutationsobject *po)
 static PyObject *
 permutations_sizeof(permutationsobject *po, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(po));
-    res += PyTuple_GET_SIZE(po->pool) * sizeof(Py_ssize_t);
-    res += po->r * sizeof(Py_ssize_t);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(po));
+    res += (size_t)PyTuple_GET_SIZE(po->pool) * sizeof(Py_ssize_t);
+    res += (size_t)po->r * sizeof(Py_ssize_t);
+    return PyLong_FromSize_t(res);
 }
 
 static int
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 2311840e221..8244202376c 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -804,12 +804,11 @@ mmap__repr__method(PyObject *self)
 static PyObject *
 mmap__sizeof__method(mmap_object *self, void *unused)
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self));
-    if (self->tagname)
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
+    if (self->tagname) {
         res += strlen(self->tagname) + 1;
-    return PyLong_FromSsize_t(res);
+    }
+    return PyLong_FromSize_t(res);
 }
 #endif
 
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 0ba6fb5b76c..f24690a02bd 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2151,10 +2151,9 @@ static PyObject *
 bytearray_sizeof_impl(PyByteArrayObject *self)
 /*[clinic end generated code: output=738abdd17951c427 input=e27320fd98a4bc5a]*/
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self)) + self->ob_alloc * sizeof(char);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
+    res += (size_t)self->ob_alloc * sizeof(char);
+    return PyLong_FromSize_t(res);
 }
 
 static PySequenceMethods bytearray_as_sequence = {
diff --git a/Objects/listobject.c b/Objects/listobject.c
index da623c9719a..0e696fbffb3 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2806,10 +2806,9 @@ static PyObject *
 list___sizeof___impl(PyListObject *self)
 /*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(self));
+    res += (size_t)self->allocated * sizeof(void*);
+    return PyLong_FromSize_t(res);
 }
 
 static PyObject *list_iter(PyObject *seq);
diff --git a/Objects/setobject.c b/Objects/setobject.c
index ae9e9b99446..fcdda2a0bca 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1957,12 +1957,11 @@ set_reduce(PySetObject *so, PyObject *Py_UNUSED(ignored))
 static PyObject *
 set_sizeof(PySetObject *so, PyObject *Py_UNUSED(ignored))
 {
-    Py_ssize_t res;
-
-    res = _PyObject_SIZE(Py_TYPE(so));
-    if (so->table != so->smalltable)
-        res = res + (so->mask + 1) * sizeof(setentry);
-    return PyLong_FromSsize_t(res);
+    size_t res = _PyObject_SIZE(Py_TYPE(so));
+    if (so->table != so->smalltable) {
+        res += ((size_t)so->mask + 1) * sizeof(setentry);
+    }
+    return PyLong_FromSize_t(res);
 }
 
 PyDoc_STRVAR(sizeof_doc, "S.__sizeof__() -> size of S in memory, in bytes");
-- 
GitLab