From 813f943c592cf225871b99cffc99304c8cbbee40 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 16 Apr 2017 09:21:44 +0300 Subject: [PATCH] bpo-29838: Add asserts for checking results of sq_length and mq_length slots. (#700) Negative result should be returned only when an error is set. --- Objects/abstract.c | 32 +++++++++++++++++++++++--------- Objects/typeobject.c | 4 +++- Python/bltinmodule.c | 4 +++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index 4a75b92e1d0..0f1ee9dbbaf 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -52,8 +52,11 @@ PyObject_Size(PyObject *o) } m = o->ob_type->tp_as_sequence; - if (m && m->sq_length) - return m->sq_length(o); + if (m && m->sq_length) { + Py_ssize_t len = m->sq_length(o); + assert(len >= 0 || PyErr_Occurred()); + return len; + } return PyMapping_Size(o); } @@ -86,7 +89,8 @@ PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue) _Py_IDENTIFIER(__length_hint__); if (_PyObject_HasLen(o)) { res = PyObject_Length(o); - if (res < 0 && PyErr_Occurred()) { + if (res < 0) { + assert(PyErr_Occurred()); if (!PyErr_ExceptionMatches(PyExc_TypeError)) { return -1; } @@ -1483,8 +1487,11 @@ PySequence_Size(PyObject *s) } m = s->ob_type->tp_as_sequence; - if (m && m->sq_length) - return m->sq_length(s); + if (m && m->sq_length) { + Py_ssize_t len = m->sq_length(s); + assert(len >= 0 || PyErr_Occurred()); + return len; + } type_error("object of type '%.200s' has no len()", s); return -1; @@ -1673,8 +1680,10 @@ PySequence_SetItem(PyObject *s, Py_ssize_t i, PyObject *o) if (i < 0) { if (m->sq_length) { Py_ssize_t l = (*m->sq_length)(s); - if (l < 0) + if (l < 0) { + assert(PyErr_Occurred()); return -1; + } i += l; } } @@ -1700,8 +1709,10 @@ PySequence_DelItem(PyObject *s, Py_ssize_t i) if (i < 0) { if (m->sq_length) { Py_ssize_t l = (*m->sq_length)(s); - if (l < 0) + if (l < 0) { + assert(PyErr_Occurred()); return -1; + } i += l; } } @@ -2038,8 +2049,11 @@ PyMapping_Size(PyObject *o) } m = o->ob_type->tp_as_mapping; - if (m && m->mp_length) - return m->mp_length(o); + if (m && m->mp_length) { + Py_ssize_t len = m->mp_length(o); + assert(len >= 0 || PyErr_Occurred()); + return len; + } type_error("object of type '%.200s' has no len()", o); return -1; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 369c72f81d3..ed50946a262 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5427,8 +5427,10 @@ getindex(PyObject *self, PyObject *arg) PySequenceMethods *sq = Py_TYPE(self)->tp_as_sequence; if (sq && sq->sq_length) { Py_ssize_t n = (*sq->sq_length)(self); - if (n < 0) + if (n < 0) { + assert(PyErr_Occurred()); return -1; + } i += n; } } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 8ae2303e98d..60d1b7cf922 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1479,8 +1479,10 @@ builtin_len(PyObject *module, PyObject *obj) Py_ssize_t res; res = PyObject_Size(obj); - if (res < 0 && PyErr_Occurred()) + if (res < 0) { + assert(PyErr_Occurred()); return NULL; + } return PyLong_FromSsize_t(res); }