fix len() when __len__() returns a non number type #5137
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 0aa0d52..a62e124 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -611,6 +611,18 @@
             def __len__(self):
                 raise ValueError
         self.assertRaises(ValueError, len, BadSeq())
+        class InvalidLen:
+            def __len__(self):
+                return None
+        self.assertRaises(TypeError, len, InvalidLen())
+        class FloatLen:
+            def __len__(self):
+                return 4.5
+        self.assertRaises(TypeError, len, FloatLen())
+        class HugeLen:
+            def __len__(self):
+                return sys.maxsize + 1
+        self.assertRaises(OverflowError, len, HugeLen())
 
     def test_map(self):
         self.assertEqual(
diff --git a/Misc/NEWS b/Misc/NEWS
index a0a8d1f..5a3b4ad 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #5137: Make len() correctly raise a TypeError when a __len__ method
+  returns a non-number type.
+
 - Issue #5182: Removed memoryview.__str__.
 
 - Issue #1717: Removed builtin cmp() function, dropped tp_compare
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 47e425c..a362b84 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4618,7 +4618,7 @@
 
 	if (res == NULL)
 		return -1;
-	len = PyLong_AsSsize_t(res);
+	len = PyNumber_AsSsize_t(res, PyExc_OverflowError);
 	Py_DECREF(res);
 	if (len < 0) {
 		if (!PyErr_Occurred())