summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-29 01:05:03 (GMT)
committerGuido van Rossum <guido@python.org>2001-09-29 01:05:03 (GMT)
commit84675acb49071977741a97d56c21967fbc520948 (patch)
treefa1cc33550906feaa6f5119b0f3a8297342577fc
parentbb29b9c952a36303bd550eb2b2e79a416ceac6ad (diff)
downloadcpython-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.c99
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;