From ce049a0aeffff6a37ebb05269e69c81b342c248a Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Fri, 14 Jul 2006 17:51:14 +0000 Subject: [PATCH] Patch #1521817: The index range checking on ctypes arrays containing exactly one element is enabled again. --- Lib/ctypes/test/test_varsize_struct.py | 65 -------------------------- Misc/NEWS | 4 ++ Modules/_ctypes/_ctypes.c | 18 ++++--- 3 files changed, 12 insertions(+), 75 deletions(-) diff --git a/Lib/ctypes/test/test_varsize_struct.py b/Lib/ctypes/test/test_varsize_struct.py index 996a630a93d..06d232315d8 100644 --- a/Lib/ctypes/test/test_varsize_struct.py +++ b/Lib/ctypes/test/test_varsize_struct.py @@ -46,70 +46,5 @@ class VarSizeTest(unittest.TestCase): self.failUnlessRaises(IndexError, array.__setitem__, -1, None) self.failUnlessRaises(IndexError, array.__getitem__, -1) - def test_varsized_array(self): - array = (c_int * 20)(20, 21, 22, 23, 24, 25, 26, 27, 28, 29) - - # no range checking is done on arrays with size == 1 - varsize_array = (c_int * 1).from_address(addressof(array)) - - # __getitem__ - self.failUnlessEqual(varsize_array[0], 20) - self.failUnlessEqual(varsize_array[1], 21) - self.failUnlessEqual(varsize_array[2], 22) - self.failUnlessEqual(varsize_array[3], 23) - self.failUnlessEqual(varsize_array[4], 24) - self.failUnlessEqual(varsize_array[5], 25) - self.failUnlessEqual(varsize_array[6], 26) - self.failUnlessEqual(varsize_array[7], 27) - self.failUnlessEqual(varsize_array[8], 28) - self.failUnlessEqual(varsize_array[9], 29) - - # still, normal sequence of length one behaviour: - self.failUnlessEqual(varsize_array[-1], 20) - self.failUnlessRaises(IndexError, lambda: varsize_array[-2]) - # except for this one, which will raise MemoryError - self.failUnlessRaises(MemoryError, lambda: varsize_array[:]) - - # __setitem__ - varsize_array[0] = 100 - varsize_array[1] = 101 - varsize_array[2] = 102 - varsize_array[3] = 103 - varsize_array[4] = 104 - varsize_array[5] = 105 - varsize_array[6] = 106 - varsize_array[7] = 107 - varsize_array[8] = 108 - varsize_array[9] = 109 - - for i in range(10): - self.failUnlessEqual(varsize_array[i], i + 100) - self.failUnlessEqual(array[i], i + 100) - - # __getslice__ - self.failUnlessEqual(varsize_array[0:10], range(100, 110)) - self.failUnlessEqual(varsize_array[1:9], range(101, 109)) - self.failUnlessEqual(varsize_array[1:-1], []) - - # __setslice__ - varsize_array[0:10] = range(1000, 1010) - self.failUnlessEqual(varsize_array[0:10], range(1000, 1010)) - - varsize_array[1:9] = range(1001, 1009) - self.failUnlessEqual(varsize_array[1:9], range(1001, 1009)) - - def test_vararray_is_sane(self): - array = (c_int * 15)(20, 21, 22, 23, 24, 25, 26, 27, 28, 29) - - varsize_array = (c_int * 1).from_address(addressof(array)) - varsize_array[:] = [1, 2, 3, 4, 5] - - self.failUnlessEqual(array[:], [1, 2, 3, 4, 5, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0]) - self.failUnlessEqual(varsize_array[0:10], [1, 2, 3, 4, 5, 25, 26, 27, 28, 29]) - - array[:5] = [10, 11, 12, 13, 14] - self.failUnlessEqual(array[:], [10, 11, 12, 13, 14, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0]) - self.failUnlessEqual(varsize_array[0:10], [10, 11, 12, 13, 14, 25, 26, 27, 28, 29]) - if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 1598cb32bcc..160bf59b969 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,10 @@ Library Extension Modules ----------------- +- Patch #1521817: Index range checking on ctypes arrays containing + exactly one element enabled again. This allows iterating over these + arrays, without the need to check the array size before. + - Bug #1521375: When the code in ctypes.util.find_library was run with root privileges, it could overwrite or delete /dev/null in certain cases; this is now fixed. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 8090f5c79d9..a56663c31dc 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -3573,7 +3573,8 @@ Array_item(PyObject *_self, Py_ssize_t index) int offset, size; StgDictObject *stgdict; - if (self->b_length == 0 || index < 0 || (self->b_length > 1 && index >= self->b_length)) { + + if (index < 0 || index >= self->b_length) { PyErr_SetString(PyExc_IndexError, "invalid index"); return NULL; @@ -3602,11 +3603,11 @@ Array_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh) if (ilow < 0) ilow = 0; - else if (ilow > self->b_length && self->b_length != 1) + else if (ilow > self->b_length) ilow = self->b_length; if (ihigh < ilow) ihigh = ilow; - else if (ihigh > self->b_length && self->b_length != 1) + else if (ihigh > self->b_length) ihigh = self->b_length; len = ihigh - ilow; @@ -3649,8 +3650,7 @@ Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value) } stgdict = PyObject_stgdict((PyObject *)self); - if (self->b_length == 0 || index < 0 - || (self->b_length > 1 && index >= self->b_length)) { + if (index < 0 || index >= stgdict->length) { PyErr_SetString(PyExc_IndexError, "invalid index"); return -1; @@ -3677,19 +3677,17 @@ Array_ass_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *va if (ilow < 0) ilow = 0; - else if (ilow > self->b_length && self->b_length != 1) + else if (ilow > self->b_length) ilow = self->b_length; - if (ihigh < 0) ihigh = 0; - if (ihigh < ilow) ihigh = ilow; - else if (ihigh > self->b_length && self->b_length != 1) + else if (ihigh > self->b_length) ihigh = self->b_length; len = PySequence_Length(value); - if (self->b_length != 1 && len != ihigh - ilow) { + if (len != ihigh - ilow) { PyErr_SetString(PyExc_ValueError, "Can only assign sequence of same size"); return -1;