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:
parent
425fcd3045
commit
3d5881ec2b
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue