From d4edfc9abffca965e76ebc5957a92031a4d6c4d4 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 30 Mar 2017 18:29:23 +0300 Subject: [PATCH] bpo-29935: Fixed error messages in the index() method of tuple, list and deque (#887) when pass indices of wrong type. --- Include/ceval.h | 2 +- Misc/NEWS | 3 +++ Modules/_collectionsmodule.c | 4 ++-- Objects/clinic/listobject.c.h | 4 ++-- Objects/clinic/tupleobject.c.h | 4 ++-- Objects/tupleobject.c | 6 +++--- Python/ceval.c | 23 ++++++++++++++++------- Tools/clinic/clinic.py | 4 ++-- 8 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Include/ceval.h b/Include/ceval.h index 25976bb3768..10be9d84eac 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -223,7 +223,7 @@ PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc); #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); -PyAPI_FUNC(int) _PyEval_SliceIndexOrNone(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); PyAPI_FUNC(void) _PyEval_SignalAsyncExc(void); #endif diff --git a/Misc/NEWS b/Misc/NEWS index 87b47829d71..9c434a7735e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- +- bpo-29935: Fixed error messages in the index() method of tuple, list and deque + when pass indices of wrong type. + - bpo-29816: Shift operation now has less opportunity to raise OverflowError. ValueError always is raised rather than OverflowError for negative counts. Shifting zero with non-negative count always returns zero. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index b0525350cf1..6f78796fd90 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1066,8 +1066,8 @@ deque_index(dequeobject *deque, PyObject **args, Py_ssize_t nargs, return NULL; } if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", &v, - _PyEval_SliceIndex, &start, - _PyEval_SliceIndex, &stop)) { + _PyEval_SliceIndexNotNone, &start, + _PyEval_SliceIndexNotNone, &stop)) { return NULL; } diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h index eeb932a240e..43d5599d7aa 100644 --- a/Objects/clinic/listobject.c.h +++ b/Objects/clinic/listobject.c.h @@ -196,7 +196,7 @@ list_index(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwna Py_ssize_t stop = PY_SSIZE_T_MAX; if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", - &value, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &stop)) { + &value, _PyEval_SliceIndexNotNone, &start, _PyEval_SliceIndexNotNone, &stop)) { goto exit; } @@ -297,4 +297,4 @@ list___reversed__(PyListObject *self, PyObject *Py_UNUSED(ignored)) { return list___reversed___impl(self); } -/*[clinic end generated code: output=2a3b75efcf858ed5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=71deae70ca0e6799 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/tupleobject.c.h b/Objects/clinic/tupleobject.c.h index 12f0df1d439..880b258dcaf 100644 --- a/Objects/clinic/tupleobject.c.h +++ b/Objects/clinic/tupleobject.c.h @@ -26,7 +26,7 @@ tuple_index(PyTupleObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kw Py_ssize_t stop = PY_SSIZE_T_MAX; if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index", - &value, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &stop)) { + &value, _PyEval_SliceIndexNotNone, &start, _PyEval_SliceIndexNotNone, &stop)) { goto exit; } @@ -99,4 +99,4 @@ tuple___getnewargs__(PyTupleObject *self, PyObject *Py_UNUSED(ignored)) { return tuple___getnewargs___impl(self); } -/*[clinic end generated code: output=561a3654411d2225 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=145bcfff64e8c809 input=a9049054013a1b77]*/ diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 9c63983d764..55da0e3a2bb 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -534,8 +534,8 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n) tuple.index value: object - start: object(converter="_PyEval_SliceIndex", type="Py_ssize_t") = 0 - stop: object(converter="_PyEval_SliceIndex", type="Py_ssize_t", c_default="PY_SSIZE_T_MAX") = sys.maxsize + start: slice_index(accept={int}) = 0 + stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize / Return first index of value. @@ -546,7 +546,7 @@ Raises ValueError if the value is not present. static PyObject * tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start, Py_ssize_t stop) -/*[clinic end generated code: output=07b6f9f3cb5c33eb input=28890d4bec234471]*/ +/*[clinic end generated code: output=07b6f9f3cb5c33eb input=fb39e9874a21fe3f]*/ { Py_ssize_t i; diff --git a/Python/ceval.c b/Python/ceval.c index e7ee772d9f6..afd305cf9af 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4892,14 +4892,10 @@ do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict) and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1. Return 0 on error, 1 on success. */ -/* Note: If v is NULL, return success without storing into *pi. This - is because_PyEval_SliceIndex() is called by apply_slice(), which can be - called by the SLICE opcode with v and/or w equal to NULL. -*/ int _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) { - if (v != NULL) { + if (v != Py_None) { Py_ssize_t x; if (PyIndex_Check(v)) { x = PyNumber_AsSsize_t(v, NULL); @@ -4918,9 +4914,22 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) } int -_PyEval_SliceIndexOrNone(PyObject *v, Py_ssize_t *pi) +_PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) { - return v == Py_None || _PyEval_SliceIndex(v, pi); + Py_ssize_t x; + if (PyIndex_Check(v)) { + x = PyNumber_AsSsize_t(v, NULL); + if (x == -1 && PyErr_Occurred()) + return 0; + } + else { + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "have an __index__ method"); + return 0; + } + *pi = x; + return 1; } diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 1d570f17c35..6be0ab2b3d1 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2670,9 +2670,9 @@ class slice_index_converter(CConverter): def converter_init(self, *, accept={int, NoneType}): if accept == {int}: - self.converter = '_PyEval_SliceIndex' + self.converter = '_PyEval_SliceIndexNotNone' elif accept == {int, NoneType}: - self.converter = '_PyEval_SliceIndexOrNone' + self.converter = '_PyEval_SliceIndex' else: fail("slice_index_converter: illegal 'accept' argument " + repr(accept))