From f368b46e168e8accdb0c578ccbba7e7d2ee8c0de Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 28 Jan 2006 19:03:25 +0000 Subject: [PATCH] Bug squashing. * Fix setting functions to check for null value (interpreted as property deletion) and raise an exception or do something else useful. * Fix conversion of read buffer to string so it returns the remainder rather than the whole thing. * Make conversions between MP and Python long work on PyObjects rather than PyLongObjects, to eliminate pointless type casts. * Fix primefield constructor argument parsing so that it doesn't crash! * Fix radix checking in MP conversions to exclude +/-1, and 0 for output. This turns into a little function now. * Do argument checking on Jacobi function. --- buffer.c | 3 ++- catacomb-python.h | 4 ++-- ec.c | 2 +- field.c | 4 ++-- group.c | 4 ++-- mp.c | 48 ++++++++++++++++++++++++++++-------------------- pgen.c | 2 +- pubkey.c | 4 +++- rand.c | 2 +- 9 files changed, 42 insertions(+), 31 deletions(-) diff --git a/buffer.c b/buffer.c index 8e4ece5..7456a3d 100644 --- a/buffer.c +++ b/buffer.c @@ -83,7 +83,7 @@ static int rbuf_pysegcount(PyObject *me, int *nn) { if (nn) *nn = BSZ(BUF_B(me)); return (1); } static int rbuf_pyreadbuf(PyObject *me, int seg, void **q) - { assert(seg == 0); *q = BBASE(BUF_B(me)); return (BSZ(BUF_B(me))); } + { assert(seg == 0); *q = BCUR(BUF_B(me)); return (BLEFT(BUF_B(me))); } static PyObject *rbmeth_skip(PyObject *me, PyObject *arg) { @@ -236,6 +236,7 @@ static PyObject *rbget_offset(PyObject *me, void *hunoz) static int rbset_offset(PyObject *me, PyObject *x, void *hunoz) { size_t n; + if (!x) NIERR("__del__"); if (!convszt(x, &n)) goto end; if (n > BSZ(BUF_B(me))) VALERR("out of range"); BCUR(BUF_B(me)) = BBASE(BUF_B(me)) + n; diff --git a/catacomb-python.h b/catacomb-python.h index 286dd9e..40ac758 100644 --- a/catacomb-python.h +++ b/catacomb-python.h @@ -296,8 +296,8 @@ extern PyTypeObject *gf_pytype; #define MP_PYCHECK(o) PyObject_TypeCheck((o), mp_pytype) #define GF_PYCHECK(o) PyObject_TypeCheck((o), gf_pytype) -extern mp *mp_frompylong(PyLongObject *); -extern PyLongObject *mp_topylong(mp *); +extern mp *mp_frompylong(PyObject *); +extern PyObject *mp_topylong(mp *); extern mp *tomp(PyObject *); extern mp *getmp(PyObject *); extern int convmp(PyObject *, void *); diff --git a/ec.c b/ec.c index 685b4bf..a64ae45 100644 --- a/ec.c +++ b/ec.c @@ -507,7 +507,7 @@ static PyObject *ecpt_pylong(PyObject *me) PyObject *rc = 0; if (EC_ATINF(ECPT_P(me))) VALERR("point at infinity"); getecptout(&p, me); - rc = (PyObject *)mp_topylong(p.x); + rc = mp_topylong(p.x); end: EC_DESTROY(&p); return (rc); diff --git a/field.c b/field.c index df6d4d4..bb99b77 100644 --- a/field.c +++ b/field.c @@ -272,7 +272,7 @@ static PyObject *fe_pyint(PyObject *x) static PyObject *fe_pylong(PyObject *x) { mp *xx = F_OUT(FE_F(x), MP_NEW, FE_X(x)); - PyObject *rc = (PyObject *)mp_topylong(xx); + PyObject *rc = mp_topylong(xx); MP_DROP(xx); return (rc); } @@ -593,7 +593,7 @@ static PyObject *primefield_pynew(PyTypeObject *ty, field *f; char *kwlist[] = { "p", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O:primefield", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:primefield", kwlist, convmp, &xx)) goto end; if ((f = field_prime(xx)) == 0) diff --git a/group.c b/group.c index dc72bc8..76dde77 100644 --- a/group.c +++ b/group.c @@ -165,7 +165,7 @@ static PyObject *meth__DHInfo_gendsa(PyObject *me, { "class", "pbits", "qbits", "seed", "event", "nsteps", 0 }; PyObject *rc = 0; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&s#|O&O&:generate", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&s#|O&O&:gendsa", kwlist, &me, convuint, &pl, convuint, &ql, &k, &ksz, convpgev, &evt, convuint, &steps)) @@ -656,7 +656,7 @@ static PyObject *ge_pylong(PyObject *me) if ((x = G_TOINT(GE_G(me), MP_NEW, GE_X(me))) == 0) TYERR("can't convert to integer"); - rc = (PyObject *)mp_topylong(x); + rc = mp_topylong(x); end: mp_drop(x); return (rc); diff --git a/mp.c b/mp.c index 4c91865..0a0e206 100644 --- a/mp.c +++ b/mp.c @@ -35,9 +35,10 @@ PyTypeObject *mp_pytype = 0; PyTypeObject *gf_pytype = 0; -mp *mp_frompylong(PyLongObject *l) +mp *mp_frompylong(PyObject *obj) { unsigned long bits; + PyLongObject *l = (PyLongObject *)obj; int sz; size_t w; mpd r = 0; @@ -71,7 +72,7 @@ mp *mp_frompylong(PyLongObject *l) return (x); } -PyLongObject *mp_topylong(mp *x) +PyObject *mp_topylong(mp *x) { unsigned long bits = mp_bits(x); int sz = (bits + SHIFT - 1)/SHIFT; @@ -83,7 +84,7 @@ PyLongObject *mp_topylong(mp *x) assert(MPW_BITS >= SHIFT); while (i < sz && p < x->vl) { - r |= *p << b; + r |= (mpd)*p++ << b; b += MPW_BITS; while (i < sz && b >= SHIFT) { l->ob_digit[i++] = r & MASK; @@ -96,15 +97,13 @@ PyLongObject *mp_topylong(mp *x) r >>= SHIFT; } l->ob_size = (x->f & MP_NEG) ? -sz : sz; - return (l); + return ((PyObject *)l); } mp *mp_frompyobject(PyObject *o, int radix) { mp *x; - if ((x = tomp(o)) != 0) - return (x); if (PyString_Check(o)) { mptext_stringctx sc; mp *x; @@ -115,6 +114,8 @@ mp *mp_frompyobject(PyObject *o, int radix) if (sc.buf < sc.lim) { MP_DROP(x); return (0); } return (x); } + if ((x = tomp(o)) != 0) + return (x); return (0); } @@ -143,6 +144,13 @@ PyObject *mp_topystring(mp *x, int radix, const char *xpre, return (o); } +static int good_radix_p(int r, int readp) +{ + return ((r >= -255 && r <= -2) || + (readp && r == 0) || + (r >= 2 && r <= 62)); +} + PyObject *mp_pywrap(mp *x) { mp_pyobj *z = PyObject_New(mp_pyobj, mp_pytype); @@ -214,7 +222,7 @@ mp *tomp(PyObject *o) } else if (PyInt_Check(o)) return (mp_fromlong(MP_NEW, PyInt_AS_LONG(o))); else if ((l = PyNumber_Long(o)) != 0) { - x = mp_frompylong((PyLongObject *)l); + x = mp_frompylong(l); Py_DECREF(l); return (x); } else { @@ -448,10 +456,10 @@ static PyObject *mp_pyint(PyObject *x) return (PyInt_FromLong(l)); } static PyObject *mp_pylong(PyObject *x) - { return (PyObject *)mp_topylong(MP_X(x)); } + { return (mp_topylong(MP_X(x))); } static PyObject *mp_pyfloat(PyObject *x) { - PyObject *l = (PyObject *)mp_topylong(MP_X(x)); + PyObject *l = mp_topylong(MP_X(x)); double f = PyLong_AsDouble(l); Py_DECREF(l); return (PyFloat_FromDouble(f)); @@ -488,10 +496,10 @@ static PyObject *mp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) int radix = 0; char *kwlist[] = { "x", "radix", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:mp", kwlist, &x, &radix)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:new", kwlist, &x, &radix)) goto end; if (MP_PYCHECK(x)) RETURN_OBJ(x); - if (radix < -255 || radix > 62) VALERR("radix out of range"); + if (!good_radix_p(radix, 1)) VALERR("bad radix"); if ((z = mp_frompyobject(x, radix)) == 0) { PyErr_Format(PyExc_TypeError, "can't convert %.100s to mp", x->ob_type->tp_name); @@ -505,10 +513,9 @@ end: static long mp_pyhash(PyObject *me) { - long i = mp_tolong(MP_X(me)); - if (i == -1) - i = -2; - return (i); + long h; + PyObject *l = mp_topylong(MP_X(me)); h = PyObject_Hash(l); + Py_DECREF(l); return (h); } static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg) @@ -517,6 +524,8 @@ static PyObject *mpmeth_jacobi(PyObject *me, PyObject *arg) PyObject *z = 0; if (!PyArg_ParseTuple(arg, "O&:jacobi", convmp, &y)) goto end; + if (MP_NEGP(MP_X(me)) || MP_EVENP(MP_X(me))) + VALERR("must be positive and odd"); z = PyInt_FromLong(mp_jacobi(y, MP_X(me))); end: if (y) MP_DROP(y); @@ -622,8 +631,7 @@ static PyObject *mpmeth_tostring(PyObject *me, PyObject *arg, PyObject *kw) char *kwlist[] = { "radix", 0 }; if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:tostring", kwlist, &radix)) goto end; - if (radix < -255 || radix > 62 || radix == -1 || radix == 0 || radix == 1) - VALERR("bad radix"); + if (!good_radix_p(radix, 0)) VALERR("bad radix"); return (mp_topystring(MP_X(me), radix, 0, 0, 0)); end: return (0); @@ -881,7 +889,7 @@ static PyObject *meth__MP_fromstring(PyObject *me, if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring", kwlist, &me, &p, &len, &r)) goto end; - if (r < -255 || r > 62) VALERR("radix out of range"); + if (!good_radix_p(r, 1)) VALERR("bad radix"); sc.buf = p; sc.lim = p + len; if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0) SYNERR("bad integer"); @@ -1683,7 +1691,7 @@ static PyObject *gf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) if (!PyArg_ParseTupleAndKeywords(arg, kw, "O|i:gf", kwlist, &x, &radix)) goto end; if (GF_PYCHECK(x)) RETURN_OBJ(x); - if (radix < -255 || radix > 62) VALERR("radix out of range"); + if (!good_radix_p(radix, 1)) VALERR("radix out of range"); if ((z = mp_frompyobject(x, radix)) == 0) { PyErr_Format(PyExc_TypeError, "can't convert %.100s to gf", x->ob_type->tp_name); @@ -1950,7 +1958,7 @@ static PyObject *meth__GF_fromstring(PyObject *me, if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|i:fromstring", kwlist, &me, &p, &len, &r)) goto end; - if (r < -255 || r > 62) VALERR("radix out of range"); + if (!good_radix_p(r, 1)) VALERR("radix out of range"); sc.buf = p; sc.lim = p + len; if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0 || MP_NEGP(zz)) z = Py_BuildValue("(Os#)", Py_None, p, len); diff --git a/pgen.c b/pgen.c index 9ffd6fb..ae4dcc5 100644 --- a/pgen.c +++ b/pgen.c @@ -129,7 +129,7 @@ end: } static PyObject *pfilt_pylong(PyObject *me) - { return ((PyObject *)mp_topylong(PFILT_F(me)->m)); } + { return (mp_topylong(PFILT_F(me)->m)); } static PyObject *pfget_x(PyObject *me, void *hunoz) { return (mp_pywrap(MP_COPY(PFILT_F(me)->m))); } diff --git a/pubkey.c b/pubkey.c index 9e50806..735a2c0 100644 --- a/pubkey.c +++ b/pubkey.c @@ -670,7 +670,9 @@ static PyObject *rsaget_rng(PyObject *me, void *hunoz) static int rsaset_rng(PyObject *me, PyObject *val, void *hunoz) { int rc = -1; - if (val != Py_None && !GRAND_PYCHECK(val)) + if (!val) + val = Py_None; + else if (val != Py_None && !GRAND_PYCHECK(val)) TYERR("expected grand or None"); Py_DECREF(RSA_RNG(me)); RSA_RNG(me) = val; diff --git a/rand.c b/rand.c index a346e12..d779846 100644 --- a/rand.c +++ b/rand.c @@ -888,7 +888,7 @@ static PyObject *bbsget_x(PyObject *me, void *hunoz) static int bbsset_x(PyObject *me, PyObject *val, void *hunoz) { - mp *x = 0; grand *r = GRAND_R(me); int rc = -1; + mp *x = 0; grand *r = GRAND_R(me); int rc = -1; if (!x) NIERR("__del__"); if ((x = getmp(val)) == 0) goto end; r->ops->misc(r, BBS_SET, x); rc = 0; end: mp_drop(x); return (rc); } -- 2.11.0