bpo-29839: Raise ValueError rather than OverflowError in len() for negative values. (#701)

This commit is contained in:
Serhiy Storchaka 2017-04-16 09:37:18 +03:00 committed by GitHub
parent 813f943c59
commit baf9f29811
3 changed files with 24 additions and 6 deletions

View File

@ -770,10 +770,18 @@ class BuiltinTest(unittest.TestCase):
def __len__(self): def __len__(self):
return 4.5 return 4.5
self.assertRaises(TypeError, len, FloatLen()) self.assertRaises(TypeError, len, FloatLen())
class NegativeLen:
def __len__(self):
return -10
self.assertRaises(ValueError, len, NegativeLen())
class HugeLen: class HugeLen:
def __len__(self): def __len__(self):
return sys.maxsize + 1 return sys.maxsize + 1
self.assertRaises(OverflowError, len, HugeLen()) self.assertRaises(OverflowError, len, HugeLen())
class HugeNegativeLen:
def __len__(self):
return -sys.maxsize-10
self.assertRaises(ValueError, len, HugeNegativeLen())
class NoLenMethod(object): pass class NoLenMethod(object): pass
self.assertRaises(TypeError, len, NoLenMethod()) self.assertRaises(TypeError, len, NoLenMethod())

View File

@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1?
Core and Builtins Core and Builtins
----------------- -----------------
- bpo-29839: len() now raises ValueError rather than OverflowError if
__len__() returned a large negative integer.
- bpo-11913: README.rst is now included in the list of distutils standard - bpo-11913: README.rst is now included in the list of distutils standard
READMEs and therefore included in source distributions. READMEs and therefore included in source distributions.

View File

@ -5924,14 +5924,21 @@ slot_sq_length(PyObject *self)
if (res == NULL) if (res == NULL)
return -1; return -1;
len = PyNumber_AsSsize_t(res, PyExc_OverflowError);
Py_DECREF(res); Py_SETREF(res, PyNumber_Index(res));
if (len < 0) { if (res == NULL)
if (!PyErr_Occurred()) return -1;
assert(PyLong_Check(res));
if (Py_SIZE(res) < 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"__len__() should return >= 0"); "__len__() should return >= 0");
return -1; return -1;
} }
len = PyNumber_AsSsize_t(res, PyExc_OverflowError);
assert(len >= 0 || PyErr_ExceptionMatches(PyExc_OverflowError));
Py_DECREF(res);
return len; return len;
} }