From 4015f62e39452db0aa651edcd54b00f4e80e6bb5 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Tue, 10 Feb 2009 15:46:50 +0000 Subject: Issue #5175: PyLong_AsUnsignedLongLong now raises OverflowError for negative arguments. Previously, it raised TypeError. Thanks Lisandro Dalcin. --- Doc/c-api/long.rst | 23 +++++++++++++++++------ Lib/test/test_struct.py | 4 ++-- Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/testcapi_long.h | 18 +++++++++++++++++- Objects/longobject.c | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 4b21fd4..5caa89e 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -155,21 +155,32 @@ Long Integer Objects .. cfunction:: PY_LONG_LONG PyLong_AsLongLong(PyObject *pylong) - Return a C :ctype:`long long` from a Python long integer. If *pylong* cannot be - represented as a :ctype:`long long`, an :exc:`OverflowError` will be raised. + .. index:: + single: OverflowError (built-in exception) + + Return a C :ctype:`long long` from a Python long integer. If + *pylong* cannot be represented as a :ctype:`long long`, an + :exc:`OverflowError` is raised and ``-1`` is returned. .. versionadded:: 2.2 .. cfunction:: unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject *pylong) - Return a C :ctype:`unsigned long long` from a Python long integer. If *pylong* - cannot be represented as an :ctype:`unsigned long long`, an :exc:`OverflowError` - will be raised if the value is positive, or a :exc:`TypeError` will be raised if - the value is negative. + .. index:: + single: OverflowError (built-in exception) + + Return a C :ctype:`unsigned long long` from a Python long integer. If + *pylong* cannot be represented as an :ctype:`unsigned long long`, an + :exc:`OverflowError` is raised and ``(unsigned long long)-1`` is + returned. .. versionadded:: 2.2 + .. versionchanged:: 2.7 + A negative *pylong* now raises :exc:`OverflowError`, not + :exc:`TypeError`. + .. cfunction:: unsigned long PyLong_AsUnsignedLongMask(PyObject *io) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index 7f5f08b..a4dc9ca 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -48,7 +48,7 @@ def with_warning_restore(func): def deprecated_err(func, *args): try: func(*args) - except (struct.error, TypeError): + except (struct.error, OverflowError): pass except DeprecationWarning: if not PY_STRUCT_OVERFLOW_MASKING: @@ -185,7 +185,7 @@ class StructTest(unittest.TestCase): def test_native_qQ(self): # can't pack -1 as unsigned regardless - self.assertRaises((struct.error, TypeError), struct.pack, "Q", -1) + self.assertRaises((struct.error, OverflowError), struct.pack, "Q", -1) # can't pack string as 'q' regardless self.assertRaises(struct.error, struct.pack, "q", "a") # ditto, but 'Q' diff --git a/Misc/ACKS b/Misc/ACKS index 48d312e..648a888 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -153,6 +153,7 @@ Simon Cross Drew Csillag John Cugini Tom Culliton +Lisandro Dalcin Andrew Dalke Lars Damerow Eric Daniel diff --git a/Misc/NEWS b/Misc/NEWS index c2d8429..536712a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -482,6 +482,9 @@ Build C-API ----- +- Issue #5175: PyLong_AsUnsignedLongLong now raises OverflowError + for negative arguments. Previously, it raised TypeError. + - Issue #4720: The format for PyArg_ParseTupleAndKeywords can begin with '|'. - Issue #3632: from the gdb debugger, the 'pyo' macro can now be called when diff --git a/Modules/testcapi_long.h b/Modules/testcapi_long.h index 8ed6b02..60ca326 100644 --- a/Modules/testcapi_long.h +++ b/Modules/testcapi_long.h @@ -97,6 +97,10 @@ TESTNAME(PyObject *error(const char*)) if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) return error( "PyLong_AsUnsignedXXX(-1) didn't complain"); + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return error( + "PyLong_AsUnsignedXXX(-1) raised " + "something other than OverflowError"); PyErr_Clear(); UNBIND(x); @@ -112,11 +116,15 @@ TESTNAME(PyObject *error(const char*)) return error( "unexpected NULL from PyNumber_Lshift"); - uout = F_PY_TO_U(x); + uout = F_PY_TO_U(x); if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) return error( "PyLong_AsUnsignedXXX(2**NBITS) didn't " "complain"); + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return error( + "PyLong_AsUnsignedXXX(2**NBITS) raised " + "something other than OverflowError"); PyErr_Clear(); /* Signed complains about 2**(NBITS-1)? @@ -132,6 +140,10 @@ TESTNAME(PyObject *error(const char*)) return error( "PyLong_AsXXX(2**(NBITS-1)) didn't " "complain"); + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return error( + "PyLong_AsXXX(2**(NBITS-1)) raised " + "something other than OverflowError"); PyErr_Clear(); /* Signed complains about -2**(NBITS-1)-1?; @@ -153,6 +165,10 @@ TESTNAME(PyObject *error(const char*)) return error( "PyLong_AsXXX(-2**(NBITS-1)-1) didn't " "complain"); + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return error( + "PyLong_AsXXX(-2**(NBITS-1)-1) raised " + "something other than OverflowError"); PyErr_Clear(); UNBIND(y); diff --git a/Objects/longobject.c b/Objects/longobject.c index fdbda6b..ddfa72b 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -557,7 +557,7 @@ _PyLong_AsByteArray(PyLongObject* v, if (Py_SIZE(v) < 0) { ndigits = -(Py_SIZE(v)); if (!is_signed) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_OverflowError, "can't convert negative long to unsigned"); return -1; } -- cgit v0.12