Commit 30532380 authored by Guido van Rossum's avatar Guido van Rossum

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.
parent add40574
...@@ -394,6 +394,8 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name) ...@@ -394,6 +394,8 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
/* /*
Calling scheme used for ternary operations: Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
v w z Action v w z Action
------------------------------------------------------------------- -------------------------------------------------------------------
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z) 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, ...@@ -425,62 +427,50 @@ ternary_op(PyObject *v,
const char *op_name) const char *op_name)
{ {
PyNumberMethods *mv, *mw, *mz; PyNumberMethods *mv, *mw, *mz;
register PyObject *x = NULL; PyObject *x = NULL;
register ternaryfunc *slot; ternaryfunc slotv = NULL;
ternaryfunc slotw = NULL;
ternaryfunc slotz = NULL;
mv = v->ob_type->tp_as_number; mv = v->ob_type->tp_as_number;
mw = w->ob_type->tp_as_number; mw = w->ob_type->tp_as_number;
if (v->ob_type != w->ob_type && mw && NEW_STYLE_NUMBER(w)) { if (mv != NULL && NEW_STYLE_NUMBER(v))
slot = NB_TERNOP(mw, op_slot); slotv = *NB_TERNOP(mv, op_slot);
if (*slot && *slot != *NB_TERNOP(mv, op_slot) && if (w->ob_type != v->ob_type &&
PyType_IsSubtype(w->ob_type, v->ob_type)) { mv != NULL && NEW_STYLE_NUMBER(w)) {
x = (*slot)(v, w, z); slotw = *NB_TERNOP(mw, op_slot);
if (x != Py_NotImplemented) if (slotw == slotv)
return x; slotw = NULL;
/* Can't do it... fall through */
Py_DECREF(x);
}
} }
if (mv != NULL && NEW_STYLE_NUMBER(v)) { if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
/* try v.op(v,w,z) */ x = slotw(v, w, z);
slot = NB_TERNOP(mv, op_slot); if (x != Py_NotImplemented)
if (*slot) { return x;
x = (*slot)(v, w, z); Py_DECREF(x); /* can't do it */
if (x != Py_NotImplemented) slotw = NULL;
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 (mw != NULL && NEW_STYLE_NUMBER(w)) { if (slotv) {
/* try w.op(v,w,z) */ x = slotv(v, w, z);
slot = NB_TERNOP(mw,op_slot); if (x != Py_NotImplemented)
if (*slot) { return x;
x = (*slot)(v, w, z); Py_DECREF(x); /* can't do it */
if (x != Py_NotImplemented) }
return x; if (slotw) {
/* Can't do it... fall through */ x = slotw(v, w, z);
Py_DECREF(x); if (x != Py_NotImplemented)
} return x;
if (NEW_STYLE_NUMBER(v) && Py_DECREF(x); /* can't do it */
(z == Py_None || z->ob_type == v->ob_type)) {
goto ternary_error;
}
} }
mz = z->ob_type->tp_as_number; mz = z->ob_type->tp_as_number;
if (mz != NULL && NEW_STYLE_NUMBER(z)) { if (mz != NULL && NEW_STYLE_NUMBER(z)) {
/* try: z.op(v,w,z) */ slotz = *NB_TERNOP(mz, op_slot);
slot = NB_TERNOP(mz, op_slot); if (slotz == slotv || slotz == slotw)
if (*slot) { slotz = NULL;
x = (*slot)(v, w, z); if (slotz) {
x = slotz(v, w, z);
if (x != Py_NotImplemented) if (x != Py_NotImplemented)
return x; return x;
/* Can't do it... fall through */ Py_DECREF(x); /* can't do it */
Py_DECREF(x);
} }
} }
...@@ -498,10 +488,10 @@ ternary_op(PyObject *v, ...@@ -498,10 +488,10 @@ ternary_op(PyObject *v,
treated as absent argument and not coerced. */ treated as absent argument and not coerced. */
if (z == Py_None) { if (z == Py_None) {
if (v->ob_type->tp_as_number) { if (v->ob_type->tp_as_number) {
slot = NB_TERNOP(v->ob_type->tp_as_number, slotz = *NB_TERNOP(v->ob_type->tp_as_number,
op_slot); op_slot);
if (*slot) if (slotz)
x = (*slot)(v, w, z); x = slotz(v, w, z);
else else
c = -1; c = -1;
} }
...@@ -521,10 +511,10 @@ ternary_op(PyObject *v, ...@@ -521,10 +511,10 @@ ternary_op(PyObject *v,
goto error1; goto error1;
if (v1->ob_type->tp_as_number != NULL) { if (v1->ob_type->tp_as_number != NULL) {
slot = NB_TERNOP(v1->ob_type->tp_as_number, slotv = *NB_TERNOP(v1->ob_type->tp_as_number,
op_slot); op_slot);
if (*slot) if (slotv)
x = (*slot)(v1, w2, z2); x = slotv(v1, w2, z2);
else else
c = -1; c = -1;
} }
...@@ -544,7 +534,6 @@ ternary_op(PyObject *v, ...@@ -544,7 +534,6 @@ ternary_op(PyObject *v,
return x; return x;
} }
ternary_error:
PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %s", PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %s",
op_name); op_name);
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment