diff options
author | Guido van Rossum <guido@python.org> | 2002-06-10 14:30:43 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2002-06-10 14:30:43 (GMT) |
commit | 2309498595cb5a69547ad87a66b4574971684ec3 (patch) | |
tree | 334b40a27e2613ef4eb20b4b4c8ce5d9ac5d9344 /Objects | |
parent | f70a0a8471fff12a4be06a2a1d643b32a7d40502 (diff) | |
download | cpython-2309498595cb5a69547ad87a66b4574971684ec3.zip cpython-2309498595cb5a69547ad87a66b4574971684ec3.tar.gz cpython-2309498595cb5a69547ad87a66b4574971684ec3.tar.bz2 |
Three's a charm: yet another fix for SF bug 551412. Thinking again
about the test case, slot_nb_power gets called on behalf of its second
argument, but with a non-None modulus it wouldn't check this, and
believes it is called on behalf of its first argument. Fix this
properly, and get rid of the code in _PyType_Lookup() that tries to
call _PyType_Ready(). But do leave a check for a NULL tp_mro there,
because this can still legitimately occur.
I'll fix this in 2.2.x too.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index cb2c791..07de6dc 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1309,22 +1309,13 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) /* Look in tp_dict of types in MRO */ mro = type->tp_mro; - if (mro == NULL) { - if (PyType_Ready(type) < 0) { - /* It's not ideal to clear the error condition, - but this function is documented as not setting - an exception, and I don't want to change that. - When PyType_Ready() can't proceed, it won't - set the "ready" flag, so future attempts to ready - the same type will call it again -- hopefully - in a context that propagates the exception out. - */ - PyErr_Clear(); - return NULL; - } - mro = type->tp_mro; - assert(mro != NULL); - } + + /* If mro is NULL, the type is either not yet initialized + by PyType_Ready(), or already cleared by type_clear(). + Either way the safest thing to do is to return NULL. */ + if (mro == NULL) + return NULL; + assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { @@ -3099,9 +3090,16 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) if (modulus == Py_None) return slot_nb_power_binary(self, other); - /* Three-arg power doesn't use __rpow__ */ - return call_method(self, "__pow__", &pow_str, - "(OO)", other, modulus); + /* Three-arg power doesn't use __rpow__. But ternary_op + can call this when the second argument's type uses + slot_nb_power, so check before calling self.__pow__. */ + if (self->ob_type->tp_as_number != NULL && + self->ob_type->tp_as_number->nb_power == slot_nb_power) { + return call_method(self, "__pow__", &pow_str, + "(OO)", other, modulus); + } + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } SLOT0(slot_nb_negative, "__neg__") |