From: Serhiy Storchaka Date: Sat, 15 Nov 2014 11:21:37 +0000 (+0200) Subject: Issue #22193: Fixed integer overflow error in sys.getsizeof(). X-Git-Tag: v3.5.0a1~481^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=030e92d1a51c2caef0c23a74e65f0aaff002158f;p=python Issue #22193: Fixed integer overflow error in sys.getsizeof(). Fixed an error in _PySys_GetSizeOf declaration. --- diff --git a/Include/sysmodule.h b/Include/sysmodule.h index 652c1e828d..cde10ac4ca 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -34,7 +34,7 @@ PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *); PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); #ifndef Py_LIMITED_API -PyAPI_DATA(size_t) _PySys_GetSizeOf(PyObject *); +PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); #endif #ifdef __cplusplus diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 93960cdc17..f8a9e5ecee 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -723,6 +723,37 @@ class SizeofTest(unittest.TestCase): # but lists are self.assertEqual(sys.getsizeof([]), vsize('Pn') + gc_header_size) + def test_errors(self): + class BadSizeof: + def __sizeof__(self): + raise ValueError + self.assertRaises(ValueError, sys.getsizeof, BadSizeof()) + + class InvalidSizeof: + def __sizeof__(self): + return None + self.assertRaises(TypeError, sys.getsizeof, InvalidSizeof()) + sentinel = ["sentinel"] + self.assertIs(sys.getsizeof(InvalidSizeof(), sentinel), sentinel) + + class FloatSizeof: + def __sizeof__(self): + return 4.5 + self.assertRaises(TypeError, sys.getsizeof, FloatSizeof()) + self.assertIs(sys.getsizeof(FloatSizeof(), sentinel), sentinel) + + class OverflowSizeof(int): + def __sizeof__(self): + return int(self) + self.assertEqual(sys.getsizeof(OverflowSizeof(sys.maxsize)), + sys.maxsize + self.gc_headsize) + with self.assertRaises(OverflowError): + sys.getsizeof(OverflowSizeof(sys.maxsize + 1)) + with self.assertRaises(ValueError): + sys.getsizeof(OverflowSizeof(-1)) + with self.assertRaises((ValueError, OverflowError)): + sys.getsizeof(OverflowSizeof(-sys.maxsize - 1)) + def test_default(self): size = test.support.calcvobjsize self.assertEqual(sys.getsizeof(True), size('') + self.longdigit) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 39fe53fb7e..106fc84fa9 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -868,7 +868,7 @@ _PySys_GetSizeOf(PyObject *o) { PyObject *res = NULL; PyObject *method; - size_t size; + Py_ssize_t size; /* Make sure the type is initialized. float gets initialized late */ if (PyType_Ready(Py_TYPE(o)) < 0) @@ -889,15 +889,20 @@ _PySys_GetSizeOf(PyObject *o) if (res == NULL) return (size_t)-1; - size = PyLong_AsSize_t(res); + size = PyLong_AsSsize_t(res); Py_DECREF(res); - if (size == (size_t)-1 && PyErr_Occurred()) + if (size == -1 && PyErr_Occurred()) + return (size_t)-1; + + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "__sizeof__() should return >= 0"); return (size_t)-1; + } /* add gc_head size */ if (PyObject_IS_GC(o)) - size += sizeof(PyGC_Head); - return size; + return ((size_t)size) + sizeof(PyGC_Head); + return (size_t)size; } static PyObject *