mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
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.
This commit is contained in:
parent
e082e7cbe4
commit
bf169915ec
5 changed files with 153 additions and 177 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue