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 /Modules/_xxsubinterpretersmodule.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 'Modules/_xxsubinterpretersmodule.c')
-rw-r--r-- | Modules/_xxsubinterpretersmodule.c | 150 |
1 files changed, 65 insertions, 85 deletions
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 19d98fd..7842947 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1405,6 +1405,34 @@ typedef struct channelid { _channels *channels; } channelid; +static int +channel_id_converter(PyObject *arg, void *ptr) +{ + int64_t cid; + if (PyObject_TypeCheck(arg, &ChannelIDtype)) { + cid = ((channelid *)arg)->id; + } + else if (PyIndex_Check(arg)) { + cid = PyLong_AsLongLong(arg); + if (cid == -1 && PyErr_Occurred()) { + return 0; + } + if (cid < 0) { + PyErr_Format(PyExc_ValueError, + "channel ID must be a non-negative int, got %R", arg); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, + "channel ID must be an int, got %.100s", + arg->ob_type->tp_name); + return 0; + } + *(int64_t *)ptr = cid; + return 1; +} + static channelid * newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, int force, int resolve) @@ -1437,28 +1465,16 @@ static PyObject * channelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; - PyObject *id; + int64_t cid; int send = -1; int recv = -1; int force = 0; int resolve = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$pppp:ChannelID.__new__", kwlist, - &id, &send, &recv, &force, &resolve)) + "O&|$pppp:ChannelID.__new__", kwlist, + channel_id_converter, &cid, &send, &recv, &force, &resolve)) return NULL; - // Coerce and check the ID. - int64_t cid; - if (PyObject_TypeCheck(id, &ChannelIDtype)) { - cid = ((channelid *)id)->id; - } - else { - cid = _Py_CoerceID(id); - if (cid < 0) { - return NULL; - } - } - // Handle "send" and "recv". if (send == 0 && recv == 0) { PyErr_SetString(PyExc_ValueError, @@ -1592,30 +1608,28 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) int equal; if (PyObject_TypeCheck(other, &ChannelIDtype)) { channelid *othercid = (channelid *)other; - if (cid->end != othercid->end) { - equal = 0; - } - else { - equal = (cid->id == othercid->id); - } + equal = (cid->end == othercid->end) && (cid->id == othercid->id); } - else { - other = PyNumber_Long(other); - if (other == NULL) { - PyErr_Clear(); - Py_RETURN_NOTIMPLEMENTED; - } - int64_t othercid = PyLong_AsLongLong(other); - Py_DECREF(other); - if (othercid == -1 && PyErr_Occurred() != NULL) { + else if (PyLong_Check(other)) { + /* Fast path */ + int overflow; + long long othercid = PyLong_AsLongLongAndOverflow(other, &overflow); + if (othercid == -1 && PyErr_Occurred()) { return NULL; } - if (othercid < 0) { - equal = 0; - } - else { - equal = (cid->id == othercid); + equal = !overflow && (othercid >= 0) && (cid->id == othercid); + } + else if (PyNumber_Check(other)) { + PyObject *pyid = PyLong_FromLongLong(cid->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)) { @@ -1754,8 +1768,7 @@ static PyTypeObject ChannelIDtype = { 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 */ channelid_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -2017,10 +2030,6 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) "O:destroy", kwlist, &id)) { return NULL; } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "ID must be an int"); - return NULL; - } // Look up the interpreter. PyInterpreterState *interp = _PyInterpreterID_LookUp(id); @@ -2145,10 +2154,6 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) &id, &code, &shared)) { return NULL; } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "first arg (ID) must be an int"); - return NULL; - } // Look up the interpreter. PyInterpreterState *interp = _PyInterpreterID_LookUp(id); @@ -2216,10 +2221,6 @@ interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) "O:is_running", kwlist, &id)) { return NULL; } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "ID must be an int"); - return NULL; - } PyInterpreterState *interp = _PyInterpreterID_LookUp(id); if (interp == NULL) { @@ -2268,13 +2269,9 @@ static PyObject * channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", NULL}; - PyObject *id; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O:channel_destroy", kwlist, &id)) { - return NULL; - } - int64_t cid = _Py_CoerceID(id); - if (cid < 0) { + int64_t cid; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_destroy", kwlist, + channel_id_converter, &cid)) { return NULL; } @@ -2331,14 +2328,10 @@ static PyObject * channel_send(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", "obj", NULL}; - PyObject *id; + int64_t cid; PyObject *obj; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OO:channel_send", kwlist, &id, &obj)) { - return NULL; - } - int64_t cid = _Py_CoerceID(id); - if (cid < 0) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:channel_send", kwlist, + channel_id_converter, &cid, &obj)) { return NULL; } @@ -2357,13 +2350,9 @@ static PyObject * channel_recv(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", NULL}; - PyObject *id; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O:channel_recv", kwlist, &id)) { - return NULL; - } - int64_t cid = _Py_CoerceID(id); - if (cid < 0) { + int64_t cid; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_recv", kwlist, + channel_id_converter, &cid)) { return NULL; } @@ -2379,17 +2368,13 @@ static PyObject * channel_close(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; - PyObject *id; + int64_t cid; int send = 0; int recv = 0; int force = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$ppp:channel_close", kwlist, - &id, &send, &recv, &force)) { - return NULL; - } - int64_t cid = _Py_CoerceID(id); - if (cid < 0) { + "O&|$ppp:channel_close", kwlist, + channel_id_converter, &cid, &send, &recv, &force)) { return NULL; } @@ -2431,17 +2416,13 @@ channel_release(PyObject *self, PyObject *args, PyObject *kwds) { // Note that only the current interpreter is affected. static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; - PyObject *id; + int64_t cid; int send = 0; int recv = 0; int force = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$ppp:channel_release", kwlist, - &id, &send, &recv, &force)) { - return NULL; - } - int64_t cid = _Py_CoerceID(id); - if (cid < 0) { + "O&|$ppp:channel_release", kwlist, + channel_id_converter, &cid, &send, &recv, &force)) { return NULL; } if (send == 0 && recv == 0) { @@ -2538,7 +2519,6 @@ PyInit__xxsubinterpreters(void) } /* Initialize types */ - ChannelIDtype.tp_base = &PyLong_Type; if (PyType_Ready(&ChannelIDtype) != 0) { return NULL; } |