diff options
author | Guido van Rossum <guido@python.org> | 2001-09-29 01:05:03 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-09-29 01:05:03 (GMT) |
commit | 84675acb49071977741a97d56c21967fbc520948 (patch) | |
tree | fa1cc33550906feaa6f5119b0f3a8297342577fc | |
parent | bb29b9c952a36303bd550eb2b2e79a416ceac6ad (diff) | |
download | cpython-84675acb49071977741a97d56c21967fbc520948.zip cpython-84675acb49071977741a97d56c21967fbc520948.tar.gz cpython-84675acb49071977741a97d56c21967fbc520948.tar.bz2 |
The changes to ternary_op could cause a core dump. Fix this, and
rewrite the code a bit to avoid calling the same slot more than once.
-rw-r--r-- | Objects/abstract.c | 99 |
1 files changed, 44 insertions, 55 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index c353159..ac95123 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -394,6 +394,8 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name) /* Calling scheme used for ternary operations: + *** In some cases, w.op is called before v.op; see binary_op1. *** + v w z Action ------------------------------------------------------------------- new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z) @@ -425,62 +427,50 @@ ternary_op(PyObject *v, const char *op_name) { PyNumberMethods *mv, *mw, *mz; - register PyObject *x = NULL; - register ternaryfunc *slot; + PyObject *x = NULL; + ternaryfunc slotv = NULL; + ternaryfunc slotw = NULL; + ternaryfunc slotz = NULL; mv = v->ob_type->tp_as_number; mw = w->ob_type->tp_as_number; - if (v->ob_type != w->ob_type && mw && NEW_STYLE_NUMBER(w)) { - slot = NB_TERNOP(mw, op_slot); - if (*slot && *slot != *NB_TERNOP(mv, op_slot) && - PyType_IsSubtype(w->ob_type, v->ob_type)) { - x = (*slot)(v, w, z); - if (x != Py_NotImplemented) - return x; - /* Can't do it... fall through */ - Py_DECREF(x); - } + if (mv != NULL && NEW_STYLE_NUMBER(v)) + slotv = *NB_TERNOP(mv, op_slot); + if (w->ob_type != v->ob_type && + mv != NULL && NEW_STYLE_NUMBER(w)) { + slotw = *NB_TERNOP(mw, op_slot); + if (slotw == slotv) + slotw = NULL; } - if (mv != NULL && NEW_STYLE_NUMBER(v)) { - /* try v.op(v,w,z) */ - slot = NB_TERNOP(mv, op_slot); - if (*slot) { - x = (*slot)(v, w, z); - if (x != Py_NotImplemented) - return x; - /* Can't do it... fall through */ - Py_DECREF(x); - } - if (v->ob_type == w->ob_type && - (z == Py_None || z->ob_type == v->ob_type)) { - goto ternary_error; - } + if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) { + x = slotw(v, w, z); + if (x != Py_NotImplemented) + return x; + Py_DECREF(x); /* can't do it */ + slotw = NULL; } - if (mw != NULL && NEW_STYLE_NUMBER(w)) { - /* try w.op(v,w,z) */ - slot = NB_TERNOP(mw,op_slot); - if (*slot) { - x = (*slot)(v, w, z); - if (x != Py_NotImplemented) - return x; - /* Can't do it... fall through */ - Py_DECREF(x); - } - if (NEW_STYLE_NUMBER(v) && - (z == Py_None || z->ob_type == v->ob_type)) { - goto ternary_error; - } + if (slotv) { + x = slotv(v, w, z); + if (x != Py_NotImplemented) + return x; + Py_DECREF(x); /* can't do it */ + } + if (slotw) { + x = slotw(v, w, z); + if (x != Py_NotImplemented) + return x; + Py_DECREF(x); /* can't do it */ } mz = z->ob_type->tp_as_number; if (mz != NULL && NEW_STYLE_NUMBER(z)) { - /* try: z.op(v,w,z) */ - slot = NB_TERNOP(mz, op_slot); - if (*slot) { - x = (*slot)(v, w, z); + slotz = *NB_TERNOP(mz, op_slot); + if (slotz == slotv || slotz == slotw) + slotz = NULL; + if (slotz) { + x = slotz(v, w, z); if (x != Py_NotImplemented) return x; - /* Can't do it... fall through */ - Py_DECREF(x); + Py_DECREF(x); /* can't do it */ } } @@ -498,10 +488,10 @@ ternary_op(PyObject *v, treated as absent argument and not coerced. */ if (z == Py_None) { if (v->ob_type->tp_as_number) { - slot = NB_TERNOP(v->ob_type->tp_as_number, - op_slot); - if (*slot) - x = (*slot)(v, w, z); + slotz = *NB_TERNOP(v->ob_type->tp_as_number, + op_slot); + if (slotz) + x = slotz(v, w, z); else c = -1; } @@ -521,10 +511,10 @@ ternary_op(PyObject *v, goto error1; if (v1->ob_type->tp_as_number != NULL) { - slot = NB_TERNOP(v1->ob_type->tp_as_number, - op_slot); - if (*slot) - x = (*slot)(v1, w2, z2); + slotv = *NB_TERNOP(v1->ob_type->tp_as_number, + op_slot); + if (slotv) + x = slotv(v1, w2, z2); else c = -1; } @@ -544,7 +534,6 @@ ternary_op(PyObject *v, return x; } -ternary_error: PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %s", op_name); return NULL; |