diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py index 93e040cdc85..145a16e91d8 100644 --- a/Lib/test/test_structmembers.py +++ b/Lib/test/test_structmembers.py @@ -3,13 +3,25 @@ from _testcapi import test_structmembersType, \ SHRT_MAX, SHRT_MIN, USHRT_MAX, \ INT_MAX, INT_MIN, UINT_MAX, \ LONG_MAX, LONG_MIN, ULONG_MAX, \ - LLONG_MAX, LLONG_MIN, ULLONG_MAX + LLONG_MAX, LLONG_MIN, ULLONG_MAX, \ + PY_SSIZE_T_MAX, PY_SSIZE_T_MIN import warnings, unittest, sys from test import support -ts=test_structmembersType(False, 1, 2, 3, 4, 5, 6, 7, 8, - 9.99999, 10.1010101010) +ts=test_structmembersType(False, # T_BOOL + 1, # T_BYTE + 2, # T_UBYTE + 3, # T_SHORT + 4, # T_USHORT + 5, # T_INT + 6, # T_UINT + 7, # T_LONG + 8, # T_ULONG + 23, # T_PYSSIZET + 9.99999,# T_FLOAT + 10.1010101010 # T_DOUBLE + ) class ReadWriteTests(unittest.TestCase): def test_types(self): @@ -47,6 +59,11 @@ class ReadWriteTests(unittest.TestCase): ts.T_ULONG = ULONG_MAX self.assertEquals(ts.T_ULONG, ULONG_MAX) + ts.T_PYSSIZET = PY_SSIZE_T_MAX + self.assertEquals(ts.T_PYSSIZET, PY_SSIZE_T_MAX) + ts.T_PYSSIZET = PY_SSIZE_T_MIN + self.assertEquals(ts.T_PYSSIZET, PY_SSIZE_T_MIN) + ## T_LONGLONG and T_ULONGLONG may not be present on some platforms if hasattr(ts, 'T_LONGLONG'): ts.T_LONGLONG = LLONG_MAX @@ -63,6 +80,27 @@ class ReadWriteTests(unittest.TestCase): ts.T_ULONGLONG = 4 self.assertEquals(ts.T_ULONGLONG, 4) + def test_bad_assignments(self): + # XXX testing of T_UINT and T_ULONG temporarily disabled; + # see issue 8014. + integer_attributes = [ + 'T_BOOL', + 'T_BYTE', 'T_UBYTE', + 'T_SHORT', 'T_USHORT', + 'T_INT', #'T_UINT', + 'T_LONG', #'T_ULONG', + 'T_PYSSIZET' + ] + + if hasattr(ts, 'T_LONGLONG'): + integer_attributes.extend(['T_LONGLONG', 'T_ULONGLONG']) + + # issue8014: this produced 'bad argument to internal function' + # internal error + for nonint in None, 3.2j, "full of eels", {}, []: + for attr in integer_attributes: + self.assertRaises(TypeError, setattr, ts, attr, nonint) + class TestWarnings(unittest.TestCase): def has_warned(self, w): diff --git a/Misc/NEWS b/Misc/NEWS index 348d524ecdb..e40100b870a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 3.2 Alpha 1? Core and Builtins ----------------- +- Issue #8014: Setting a T_UINT or T_PYSSIZET attribute of an object with + PyMemberDefs could produce an internal error; raise TypeError instead. + - Issue #7845: Rich comparison methods on the complex type now return NotImplemented rather than raising a TypeError when comparing with an incompatible type; this allows user-defined classes to implement their own diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 38243880f7b..1be3c66a146 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2084,6 +2084,7 @@ typedef struct { unsigned int uint_member; long long_member; unsigned long ulong_member; + Py_ssize_t pyssizet_member; float float_member; double double_member; #ifdef HAVE_LONG_LONG @@ -2107,6 +2108,7 @@ static struct PyMemberDef test_members[] = { {"T_UINT", T_UINT, offsetof(test_structmembers, structmembers.uint_member), 0, NULL}, {"T_LONG", T_LONG, offsetof(test_structmembers, structmembers.long_member), 0, NULL}, {"T_ULONG", T_ULONG, offsetof(test_structmembers, structmembers.ulong_member), 0, NULL}, + {"T_PYSSIZET", T_PYSSIZET, offsetof(test_structmembers, structmembers.pyssizet_member), 0, NULL}, {"T_FLOAT", T_FLOAT, offsetof(test_structmembers, structmembers.float_member), 0, NULL}, {"T_DOUBLE", T_DOUBLE, offsetof(test_structmembers, structmembers.double_member), 0, NULL}, #ifdef HAVE_LONG_LONG @@ -2122,13 +2124,13 @@ test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { static char *keywords[] = { "T_BOOL", "T_BYTE", "T_UBYTE", "T_SHORT", "T_USHORT", - "T_INT", "T_UINT", "T_LONG", "T_ULONG", + "T_INT", "T_UINT", "T_LONG", "T_ULONG", "T_PYSSIZET", "T_FLOAT", "T_DOUBLE", -#ifdef HAVE_LONG_LONG +#ifdef HAVE_LONG_LONG "T_LONGLONG", "T_ULONGLONG", #endif NULL}; - static char *fmt = "|bbBhHiIlkfd" + static char *fmt = "|bbBhHiIlknfd" #ifdef HAVE_LONG_LONG "LK" #endif @@ -2145,9 +2147,10 @@ test_structmembers_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) &ob->structmembers.short_member, &ob->structmembers.ushort_member, &ob->structmembers.int_member, - &ob->structmembers.uint_member, + &ob->structmembers.uint_member, &ob->structmembers.long_member, &ob->structmembers.ulong_member, + &ob->structmembers.pyssizet_member, &ob->structmembers.float_member, &ob->structmembers.double_member #ifdef HAVE_LONG_LONG diff --git a/Objects/longobject.c b/Objects/longobject.c index ce87084e282..d182e7ce30e 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -435,10 +435,15 @@ PyLong_AsSsize_t(PyObject *vv) { Py_ssize_t i; int sign; - if (vv == NULL || !PyLong_Check(vv)) { + if (vv == NULL) { PyErr_BadInternalCall(); return -1; } + if (!PyLong_Check(vv)) { + PyErr_SetString(PyExc_TypeError, "an integer is required"); + return -1; + } + v = (PyLongObject *)vv; i = Py_SIZE(v); switch (i) { @@ -485,10 +490,15 @@ PyLong_AsUnsignedLong(PyObject *vv) unsigned long x, prev; Py_ssize_t i; - if (vv == NULL || !PyLong_Check(vv)) { + if (vv == NULL) { PyErr_BadInternalCall(); - return (unsigned long) -1; + return (unsigned long)-1; } + if (!PyLong_Check(vv)) { + PyErr_SetString(PyExc_TypeError, "an integer is required"); + return (unsigned long)-1; + } + v = (PyLongObject *)vv; i = Py_SIZE(v); x = 0; @@ -523,10 +533,15 @@ PyLong_AsSize_t(PyObject *vv) size_t x, prev; Py_ssize_t i; - if (vv == NULL || !PyLong_Check(vv)) { + if (vv == NULL) { PyErr_BadInternalCall(); - return (unsigned long) -1; + return (size_t) -1; } + if (!PyLong_Check(vv)) { + PyErr_SetString(PyExc_TypeError, "an integer is required"); + return (size_t)-1; + } + v = (PyLongObject *)vv; i = Py_SIZE(v); x = 0;