summaryrefslogtreecommitdiff
path: root/Objects/interpreteridobject.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-09-13 22:50:27 +0300
committerGitHub <noreply@github.com>2019-09-13 22:50:27 +0300
commitbf169915ecdd42329726104278eb723a7dda2736 (patch)
treea7d78e17ab50c98822a9ea307068a1eac9531faa /Objects/interpreteridobject.c
parente082e7cbe4a934b86f7a07354d97d4e14a9dd46a (diff)
downloadcpython-git-bf169915ecdd42329726104278eb723a7dda2736.tar.gz
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.c100
1 files changed, 49 insertions, 51 deletions
diff --git a/Objects/interpreteridobject.c b/Objects/interpreteridobject.c
index 0a1dfa2579..3edbb85e6a 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);
}