Skip to content

Commit 030e92d

Browse files
Issue python#22193: Fixed integer overflow error in sys.getsizeof().
Fixed an error in _PySys_GetSizeOf declaration.
1 parent ed73010 commit 030e92d

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

Include/sysmodule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *);
3434
PyAPI_FUNC(PyObject *) PySys_GetXOptions(void);
3535

3636
#ifndef Py_LIMITED_API
37-
PyAPI_DATA(size_t) _PySys_GetSizeOf(PyObject *);
37+
PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *);
3838
#endif
3939

4040
#ifdef __cplusplus

Lib/test/test_sys.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,37 @@ def test_gc_head_size(self):
723723
# but lists are
724724
self.assertEqual(sys.getsizeof([]), vsize('Pn') + gc_header_size)
725725

726+
def test_errors(self):
727+
class BadSizeof:
728+
def __sizeof__(self):
729+
raise ValueError
730+
self.assertRaises(ValueError, sys.getsizeof, BadSizeof())
731+
732+
class InvalidSizeof:
733+
def __sizeof__(self):
734+
return None
735+
self.assertRaises(TypeError, sys.getsizeof, InvalidSizeof())
736+
sentinel = ["sentinel"]
737+
self.assertIs(sys.getsizeof(InvalidSizeof(), sentinel), sentinel)
738+
739+
class FloatSizeof:
740+
def __sizeof__(self):
741+
return 4.5
742+
self.assertRaises(TypeError, sys.getsizeof, FloatSizeof())
743+
self.assertIs(sys.getsizeof(FloatSizeof(), sentinel), sentinel)
744+
745+
class OverflowSizeof(int):
746+
def __sizeof__(self):
747+
return int(self)
748+
self.assertEqual(sys.getsizeof(OverflowSizeof(sys.maxsize)),
749+
sys.maxsize + self.gc_headsize)
750+
with self.assertRaises(OverflowError):
751+
sys.getsizeof(OverflowSizeof(sys.maxsize + 1))
752+
with self.assertRaises(ValueError):
753+
sys.getsizeof(OverflowSizeof(-1))
754+
with self.assertRaises((ValueError, OverflowError)):
755+
sys.getsizeof(OverflowSizeof(-sys.maxsize - 1))
756+
726757
def test_default(self):
727758
size = test.support.calcvobjsize
728759
self.assertEqual(sys.getsizeof(True), size('') + self.longdigit)

Python/sysmodule.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ _PySys_GetSizeOf(PyObject *o)
868868
{
869869
PyObject *res = NULL;
870870
PyObject *method;
871-
size_t size;
871+
Py_ssize_t size;
872872

873873
/* Make sure the type is initialized. float gets initialized late */
874874
if (PyType_Ready(Py_TYPE(o)) < 0)
@@ -889,15 +889,20 @@ _PySys_GetSizeOf(PyObject *o)
889889
if (res == NULL)
890890
return (size_t)-1;
891891

892-
size = PyLong_AsSize_t(res);
892+
size = PyLong_AsSsize_t(res);
893893
Py_DECREF(res);
894-
if (size == (size_t)-1 && PyErr_Occurred())
894+
if (size == -1 && PyErr_Occurred())
895+
return (size_t)-1;
896+
897+
if (size < 0) {
898+
PyErr_SetString(PyExc_ValueError, "__sizeof__() should return >= 0");
895899
return (size_t)-1;
900+
}
896901

897902
/* add gc_head size */
898903
if (PyObject_IS_GC(o))
899-
size += sizeof(PyGC_Head);
900-
return size;
904+
return ((size_t)size) + sizeof(PyGC_Head);
905+
return (size_t)size;
901906
}
902907

903908
static PyObject *

0 commit comments

Comments
 (0)