From bf8910bde6a430a64868ef70319f94e94114c82c Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 5 Apr 2006 12:20:57 +0100 Subject: [PATCH] mp: Be more restrictive about implicit conversions. Implicit conversions, e.g., for binary operators, used to be quite promiscuous. In particular, if P is a curve point and x is an MP, then P * x was a point multiplication, but x * P converted P to an integer (by discarding the y coordinate) and multiplied in integers. This is clearly insane. The new code is pickier about converting things to MPs or GFs. Explicit conversions can still be given. And there will still be great confusion if you mix Catacomb types with other numeric types. But things seem more logical now, at least. The actual implicit conversion rules are as follows: * An MP and any type with a `long' conversion /except/ for GF, FE, ECPt or GE may convert to MP. * A GF and any type with a `long' conversion /except/ for MP, FE, ECPt or GE may convert to GF. * Anything which can convert to `long' may convert to FE. This will lead to confusion if you mix FEs and ECPts, but I think that's asking for trouble anyway. * There are no implicit conversions to ECPt or GE. However, ECPt can be multiplied by anything with a `long' conversion. I hope this is right. If not, I'll fiddle some more. --- mp.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/mp.c b/mp.c index f31691e..00b728d 100644 --- a/mp.c +++ b/mp.c @@ -269,11 +269,44 @@ int convgf(PyObject *o, void *p) return (1); } +static mp *implicitmp(PyObject *o) +{ + if (!o || + GF_PYCHECK(o) || + ECPT_PYCHECK(o) || + FE_PYCHECK(o) || + GE_PYCHECK(o)) + return (0); + return (tomp(o)); +} + +static mp *implicitgf(PyObject *o) +{ + if (!o || + MP_PYCHECK(o) || + ECPT_PYCHECK(o) || + FE_PYCHECK(o) || + GE_PYCHECK(o)) + return (0); + return (tomp(o)); +} + static int mpbinop(PyObject *x, PyObject *y, mp **xx, mp **yy) { - if ((*xx = tomp(x)) == 0) + if ((*xx = implicitmp(x)) == 0) + return (-1); + if ((*yy = implicitmp(y)) == 0) { + MP_DROP(*xx); + return (-1); + } + return (0); +} + +static int gfbinop(PyObject *x, PyObject *y, mp **xx, mp **yy) +{ + if ((*xx = implicitgf(x)) == 0) return (-1); - if ((*yy = tomp(y)) == 0) { + if ((*yy = implicitgf(y)) == 0) { MP_DROP(*xx); return (-1); } @@ -286,7 +319,7 @@ static int mpbinop(PyObject *x, PyObject *y, mp **xx, mp **yy) #define BINOP(pre, name) \ static PyObject *pre##_py##name(PyObject *x, PyObject *y) { \ mp *xx, *yy, *zz; \ - if (mpbinop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ + if (pre##binop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ zz = pre##_##name(MP_NEW, xx, yy); \ MP_DROP(xx); MP_DROP(yy); \ return (pre##_pywrap(zz)); \ @@ -330,7 +363,7 @@ static PyObject *mp_pyid(PyObject *x) { RETURN_OBJ(x); } mp *xx, *yy; \ PyObject *z = 0; \ long n; \ - if (mpbinop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ + if (pre##binop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ if (mp_tolong_checked(yy, &n)) goto end; \ if (n < 0) \ z = pre##_pywrap(mp_##rname(MP_NEW, xx, -n)); \ @@ -351,7 +384,7 @@ SHIFTOP(gf, lsr, lsl) mp *xx, *yy; \ PyObject *z = 0; \ INIT_##qq(q) INIT_##rr(r) \ - if (mpbinop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ + if (pre##binop(x, y, &xx, &yy)) RETURN_NOTIMPL; \ if (MP_ZEROP(yy)) \ ZDIVERR("division by zero"); \ pre##_div(ARG_##qq(q), ARG_##rr(r), xx, yy); \ @@ -396,7 +429,7 @@ static PyObject *mp_pyexp(PyObject *x, PyObject *y, PyObject *z) mp *r = 0; PyObject *rc = 0; - if ((xx = tomp(x)) == 0 || (yy = tomp(y)) == 0 || + if ((xx = implicitmp(x)) == 0 || (yy = implicitmp(y)) == 0 || (z && z != Py_None && (zz = tomp(z)) == 0)) { mp_drop(xx); mp_drop(yy); mp_drop(zz); RETURN_NOTIMPL; @@ -876,7 +909,7 @@ Notes:\n\ }; static PyObject *meth__MP_fromstring(PyObject *me, - PyObject *arg, PyObject *kw) + PyObject *arg, PyObject *kw) { int r = 0; char *p; @@ -1772,7 +1805,7 @@ static PyObject *gf_pyrichcompare(PyObject *x, PyObject *y, int op) int xl, yl; int b; - if (mpbinop(x, y, &xx, &yy)) RETURN_NOTIMPL; + if (gfbinop(x, y, &xx, &yy)) RETURN_NOTIMPL; switch (op) { case Py_EQ: b = MP_EQ(xx, yy); break; case Py_NE: b = !MP_EQ(xx, yy); break; -- 2.11.0