]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #12909: Make PyLong_As* functions consistent in their use of exceptions.
authorNadeem Vawda <nadeem.vawda@gmail.com>
Wed, 7 Sep 2011 19:40:26 +0000 (21:40 +0200)
committerNadeem Vawda <nadeem.vawda@gmail.com>
Wed, 7 Sep 2011 19:40:26 +0000 (21:40 +0200)
PyLong_AsDouble() and PyLong_AsUnsignedLongLong() now raise TypeError (rather
than SystemError) when passed a non-integer argument, matching the behavior of
all the other PyLong_As*() functions.

Modules/_testcapimodule.c
Modules/testcapi_long.h
Objects/longobject.c

index 51c79c9634ce99eb9cdf069d93581715ceb1a7d5..456a8a59ec793cfb2f1d3ab541380828ee8b84a5 100644 (file)
@@ -769,6 +769,68 @@ test_long_long_and_overflow(PyObject *self)
     return Py_None;
 }
 
+/* Test the PyLong_As{Size,Ssize}_t API. At present this just tests that
+   non-integer arguments are handled correctly. It should be extended to
+   test overflow handling.
+ */
+
+static PyObject *
+test_long_as_size_t(PyObject *self)
+{
+    size_t out_u;
+    Py_ssize_t out_s;
+
+    Py_INCREF(Py_None);
+
+    out_u = PyLong_AsSize_t(Py_None);
+    if (out_u != (size_t)-1 || !PyErr_Occurred())
+        return raiseTestError("test_long_as_size_t",
+                              "PyLong_AsSize_t(None) didn't complain");
+    if (!PyErr_ExceptionMatches(PyExc_TypeError))
+        return raiseTestError("test_long_as_size_t",
+                              "PyLong_AsSize_t(None) raised "
+                              "something other than TypeError");
+    PyErr_Clear();
+
+    out_s = PyLong_AsSsize_t(Py_None);
+    if (out_s != (Py_ssize_t)-1 || !PyErr_Occurred())
+        return raiseTestError("test_long_as_size_t",
+                              "PyLong_AsSsize_t(None) didn't complain");
+    if (!PyErr_ExceptionMatches(PyExc_TypeError))
+        return raiseTestError("test_long_as_size_t",
+                              "PyLong_AsSsize_t(None) raised "
+                              "something other than TypeError");
+    PyErr_Clear();
+
+    /* Py_INCREF(Py_None) omitted - we already have a reference to it. */
+    return Py_None;
+}
+
+/* Test the PyLong_AsDouble API. At present this just tests that
+   non-integer arguments are handled correctly.
+ */
+
+static PyObject *
+test_long_as_double(PyObject *self)
+{
+    double out;
+
+    Py_INCREF(Py_None);
+
+    out = PyLong_AsDouble(Py_None);
+    if (out != -1.0 || !PyErr_Occurred())
+        return raiseTestError("test_long_as_double",
+                              "PyLong_AsDouble(None) didn't complain");
+    if (!PyErr_ExceptionMatches(PyExc_TypeError))
+        return raiseTestError("test_long_as_double",
+                              "PyLong_AsDouble(None) raised "
+                              "something other than TypeError");
+    PyErr_Clear();
+
+    /* Py_INCREF(Py_None) omitted - we already have a reference to it. */
+    return Py_None;
+}
+
 /* Test the L code for PyArg_ParseTuple.  This should deliver a PY_LONG_LONG
    for both long and int arguments.  The test may leak a little memory if
    it fails.
@@ -2267,6 +2329,8 @@ static PyMethodDef TestMethods[] = {
     {"test_long_api",           (PyCFunction)test_long_api,      METH_NOARGS},
     {"test_long_and_overflow", (PyCFunction)test_long_and_overflow,
      METH_NOARGS},
+    {"test_long_as_double",     (PyCFunction)test_long_as_double,METH_NOARGS},
+    {"test_long_as_size_t",     (PyCFunction)test_long_as_size_t,METH_NOARGS},
     {"test_long_numbits",       (PyCFunction)test_long_numbits,  METH_NOARGS},
     {"test_k_code",             (PyCFunction)test_k_code,        METH_NOARGS},
     {"test_empty_argparse", (PyCFunction)test_empty_argparse,METH_NOARGS},
index fa94fd6beaa53dd30284052339f060389c3c1ec5..5784452edfccc4d3d191b9c6a9619ec3cc4b6911 100644 (file)
@@ -177,6 +177,32 @@ TESTNAME(PyObject *error(const char*))
         Py_DECREF(one);
     }
 
+    /* Test F_PY_TO_{S,U} on non-pylong input. This should raise a TypeError. */
+    {
+        TYPENAME out;
+        unsigned TYPENAME uout;
+
+        Py_INCREF(Py_None);
+
+        out = F_PY_TO_S(Py_None);
+        if (out != (TYPENAME)-1 || !PyErr_Occurred())
+            return error("PyLong_AsXXX(None) didn't complain");
+        if (!PyErr_ExceptionMatches(PyExc_TypeError))
+            return error("PyLong_AsXXX(None) raised "
+                         "something other than TypeError");
+        PyErr_Clear();
+
+        uout = F_PY_TO_U(Py_None);
+        if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
+            return error("PyLong_AsXXX(None) didn't complain");
+        if (!PyErr_ExceptionMatches(PyExc_TypeError))
+            return error("PyLong_AsXXX(None) raised "
+                         "something other than TypeError");
+        PyErr_Clear();
+
+        Py_DECREF(Py_None);
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
index 5df519cfdbc981fde0076024fcba0c483920d906..8f6f18f0a6454ea967c25fcffe0dd4864dd223ed 100644 (file)
@@ -1193,10 +1193,14 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
     int one = 1;
     int res;
 
-    if (vv == NULL || !PyLong_Check(vv)) {
+    if (vv == NULL) {
         PyErr_BadInternalCall();
         return (unsigned PY_LONG_LONG)-1;
     }
+    if (!PyLong_Check(vv)) {
+        PyErr_SetString(PyExc_TypeError, "an integer is required");
+        return (unsigned PY_LONG_LONG)-1;
+    }
 
     v = (PyLongObject*)vv;
     switch(Py_SIZE(v)) {
@@ -2481,10 +2485,14 @@ PyLong_AsDouble(PyObject *v)
     Py_ssize_t exponent;
     double x;
 
-    if (v == NULL || !PyLong_Check(v)) {
+    if (v == NULL) {
         PyErr_BadInternalCall();
         return -1.0;
     }
+    if (!PyLong_Check(v)) {
+        PyErr_SetString(PyExc_TypeError, "an integer is required");
+        return -1.0;
+    }
     x = _PyLong_Frexp((PyLongObject *)v, &exponent);
     if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) {
         PyErr_SetString(PyExc_OverflowError,