rand.c: Careful range checking on `block' and `mp'.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 12 Sep 2016 21:26:09 +0000 (22:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 12 Sep 2016 21:33:23 +0000 (22:33 +0100)
  * For `mp', don't allow the `or' mask to be wider than the requested
    result.

  * For `range', insist that the limit is strictly positive, so that the
    output range is actually inhabited.

These parallel currently unreleased fixes to the underlying library,
which are required for things to work properly; so bump the dependency.

debian/control
rand.c

index c52c8d8..444feba 100644 (file)
@@ -5,7 +5,7 @@ XS-Python-Version: >= 2.6, << 2.8
 Maintainer: Mark Wooding <mdw@distorted.org.uk>
 Build-Depends: debhelper (>= 9), pkg-config,
        python, python2.6-dev, python2.7-dev,
-       mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.2.0)
+       mlib-dev (>= 2.2.2.1), catacomb-dev (>= 2.2.5+14)
 Standards-Version: 3.8.0
 
 Package: python-catacomb
diff --git a/rand.c b/rand.c
index 6e1d05e..4fcb155 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -90,20 +90,20 @@ static PyObject *grmeth_range(PyObject *me, PyObject *arg)
   if (!PyArg_ParseTuple(arg, "O:range", &m)) return (0);
   if (PyInt_Check(m)) {
     long mm = PyInt_AS_LONG(m);
-    if (mm < 0)
-      goto negative;
+    if (mm <= 0)
+      goto notpos;
     if (mm <= 0xffffffff)
       return (PyInt_FromLong(grand_range(GRAND_R(me), mm)));
   }
   if ((x = getmp(m)) == 0)
     goto end;
-  if (MP_NEGP(x))
-    goto negative;
+  if (!MP_POSP(x))
+    goto notpos;
   y = mprand_range(MP_NEW, x, GRAND_R(me), 0);
   MP_DROP(x);
   return (mp_pywrap(y));
-negative:
-  TYERR("range must be nonnegative");
+notpos:
+  VALERR("range must be strictly positive");
 end:
   if (x) MP_DROP(x);
   return (0);
@@ -112,12 +112,13 @@ end:
 static PyObject *grmeth_mp(PyObject *me, PyObject *arg, PyObject *kw)
 {
   size_t l;
-  mpw o;
+  mpw o = 0;
   char *kwlist[] = { "bits", "or", 0 };
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", kwlist,
                                   convszt, &l, convmpw, &o))
     goto end;
+  if (l < MPW_BITS && (o >> l)) VALERR("or mask too large");
   return (mp_pywrap(mprand(MP_NEW, l, GRAND_R(me), o)));
 end:
   return (0);