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.
This commit is contained in:
Nadeem Vawda 2011-09-07 21:40:26 +02:00
parent 425fcd3045
commit 3d5881ec2b
3 changed files with 100 additions and 2 deletions

View 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},

View 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;
}

View 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,