[Python-checkins] cpython: Issue #12909: Make PyLong_As* functions consistent in their use of exceptions.

nadeem.vawda python-checkins at python.org
Wed Sep 7 21:41:18 CEST 2011


http://hg.python.org/cpython/rev/4a66a35da3fd
changeset:   72312:4a66a35da3fd
user:        Nadeem Vawda <nadeem.vawda at gmail.com>
date:        Wed Sep 07 21:40:26 2011 +0200
summary:
  Issue #12909: Make PyLong_As* functions consistent in their use of exceptions.

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.

files:
  Modules/_testcapimodule.c |  64 +++++++++++++++++++++++++++
  Modules/testcapi_long.h   |  26 ++++++++++
  Objects/longobject.c      |  12 ++++-
  3 files changed, 100 insertions(+), 2 deletions(-)


diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -769,6 +769,68 @@
     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 @@
     {"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},
diff --git a/Modules/testcapi_long.h b/Modules/testcapi_long.h
--- a/Modules/testcapi_long.h
+++ b/Modules/testcapi_long.h
@@ -177,6 +177,32 @@
         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;
 }
diff --git a/Objects/longobject.c b/Objects/longobject.c
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -1193,10 +1193,14 @@
     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 @@
     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,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list