diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-09-13 19:50:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-13 19:50:27 (GMT) |
commit | bf169915ecdd42329726104278eb723a7dda2736 (patch) | |
tree | a7d78e17ab50c98822a9ea307068a1eac9531faa /Objects/interpreteridobject.c | |
parent | e082e7cbe4a934b86f7a07354d97d4e14a9dd46a (diff) | |
download | cpython-bf169915ecdd42329726104278eb723a7dda2736.zip cpython-bf169915ecdd42329726104278eb723a7dda2736.tar.gz cpython-bf169915ecdd42329726104278eb723a7dda2736.tar.bz2 |
bpo-38005: Fixed comparing and creating of InterpreterID and ChannelID. (GH-15652)
* Fix a crash in comparing with float (and maybe other crashes).
* They are now never equal to strings and non-integer numbers.
* Comparison with a large number no longer raises OverflowError.
* Arbitrary exceptions no longer silenced in constructors and comparisons.
* TypeError raised in the constructor contains now the name of the type.
* Accept only ChannelID and int-like objects in channel functions.
* Accept only InterpreterId, int-like objects and str in the InterpreterId constructor.
* Accept int-like objects, not just int in interpreter related functions.
Diffstat (limited to 'Objects/interpreteridobject.c')
-rw-r--r-- | Objects/interpreteridobject.c | 100 |
1 files changed, 49 insertions, 51 deletions
diff --git a/Objects/interpreteridobject.c b/Objects/interpreteridobject.c index 0a1dfa2..3edbb85 100644 --- a/Objects/interpreteridobject.c +++ b/Objects/interpreteridobject.c @@ -5,38 +5,6 @@ #include "interpreteridobject.h" -int64_t -_Py_CoerceID(PyObject *orig) -{ - PyObject *pyid = PyNumber_Long(orig); - if (pyid == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_Format(PyExc_TypeError, - "'id' must be a non-negative int, got %R", orig); - } - else { - PyErr_Format(PyExc_ValueError, - "'id' must be a non-negative int, got %R", orig); - } - return -1; - } - int64_t id = PyLong_AsLongLong(pyid); - Py_DECREF(pyid); - if (id == -1 && PyErr_Occurred() != NULL) { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) { - PyErr_Format(PyExc_ValueError, - "'id' must be a non-negative int, got %R", orig); - } - return -1; - } - if (id < 0) { - PyErr_Format(PyExc_ValueError, - "'id' must be a non-negative int, got %R", orig); - return -1; - } - return id; -} - typedef struct interpid { PyObject_HEAD int64_t id; @@ -85,8 +53,31 @@ interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) id = ((interpid *)idobj)->id; } else { - id = _Py_CoerceID(idobj); + PyObject *pyid; + if (PyIndex_Check(idobj)) { + pyid = idobj; + Py_INCREF(pyid); + } + else if (PyUnicode_Check(idobj)) { + pyid = PyNumber_Long(idobj); + if (pyid == NULL) { + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "interpreter ID must be an int, got %.100s", + idobj->ob_type->tp_name); + return NULL; + } + id = PyLong_AsLongLong(pyid); + Py_DECREF(pyid); + if (id == -1 && PyErr_Occurred()) { + return NULL; + } if (id < 0) { + PyErr_Format(PyExc_ValueError, + "interpreter ID must be a non-negative int, got %R", idobj); return NULL; } } @@ -202,23 +193,26 @@ interpid_richcompare(PyObject *self, PyObject *other, int op) interpid *otherid = (interpid *)other; equal = (id->id == otherid->id); } - else { - other = PyNumber_Long(other); - if (other == NULL) { - PyErr_Clear(); - Py_RETURN_NOTIMPLEMENTED; - } - int64_t otherid = PyLong_AsLongLong(other); - Py_DECREF(other); - if (otherid == -1 && PyErr_Occurred() != NULL) { + else if (PyLong_CheckExact(other)) { + /* Fast path */ + int overflow; + long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow); + if (otherid == -1 && PyErr_Occurred()) { return NULL; } - if (otherid < 0) { - equal = 0; - } - else { - equal = (id->id == otherid); + equal = !overflow && (otherid >= 0) && (id->id == otherid); + } + else if (PyNumber_Check(other)) { + PyObject *pyid = PyLong_FromLongLong(id->id); + if (pyid == NULL) { + return NULL; } + PyObject *res = PyObject_RichCompare(pyid, other, op); + Py_DECREF(pyid); + return res; + } + else { + Py_RETURN_NOTIMPLEMENTED; } if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { @@ -250,8 +244,7 @@ PyTypeObject _PyInterpreterID_Type = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_LONG_SUBCLASS, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ interpid_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -262,7 +255,7 @@ PyTypeObject _PyInterpreterID_Type = { 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ - &PyLong_Type, /* tp_base */ + 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ @@ -297,12 +290,17 @@ _PyInterpreterID_LookUp(PyObject *requested_id) if (PyObject_TypeCheck(requested_id, &_PyInterpreterID_Type)) { id = ((interpid *)requested_id)->id; } - else { + else if (PyIndex_Check(requested_id)) { id = PyLong_AsLongLong(requested_id); if (id == -1 && PyErr_Occurred() != NULL) { return NULL; } assert(id <= INT64_MAX); } + else { + PyErr_Format(PyExc_TypeError, "interpreter ID must be an int, got %.100s", + requested_id->ob_type->tp_name); + return NULL; + } return _PyInterpreterState_LookUpID(id); } |