diff --git a/Include/sysmodule.h b/Include/sysmodule.h
index 652c1e828d0bd194745e36ca0faf01523d263875..cde10ac4cafad9023e80591035e561826f7e7f03 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 93bb0ef4958926b14a0326bcd2e2799c57a7a652..9ac105fe3882f08850cb372627114637693e77f4 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -770,6 +770,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 39fe53fb7eeb47eb415e09c091ce0f8c7aa0ad60..106fc84fa997b03267e53ece9fd3ada2df2c8b87 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 *