diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-12-04 12:38:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-04 12:38:07 +0200 |
commit | 93d7918f77278f973a4a106c1d01ad2d9805816d (patch) | |
tree | f20159e9bbab7695d6c69e42937edf48c08bfb63 | |
parent | eab421bff954e4fb77516bfe6c98d30ced1412d0 (diff) | |
download | cpython-git-93d7918f77278f973a4a106c1d01ad2d9805816d.tar.gz |
[2.7] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006). (GH-7441)
(cherry picked from commit 735abadd5bd91db4a9e6f4311969b0afacca0a1a)
Co-Authored-By: Segev Finer <segev208@gmail.com>
-rw-r--r-- | Lib/ctypes/test/test_arrays.py | 7 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst | 1 | ||||
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 24 |
3 files changed, 26 insertions, 6 deletions
diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 49aaab52b9..53859a3e5e 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -1,4 +1,6 @@ import unittest +from test.support import precisionbigmemtest, _2G +import sys from ctypes import * from ctypes.test import need_symbol @@ -132,5 +134,10 @@ class ArrayTestCase(unittest.TestCase): t2 = my_int * 1 self.assertIs(t1, t2) + @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') + @precisionbigmemtest(size=_2G, memuse=1, dry_run=False) + def test_large_array(self, size): + a = c_char * size + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst new file mode 100644 index 0000000000..afaff736bf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst @@ -0,0 +1 @@ +Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fabbdf13e9..9b289af91b 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1460,24 +1460,36 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyTypeObject *result; StgDictObject *stgdict; StgDictObject *itemdict; - PyObject *proto; + PyObject *proto, *length_attr; PyObject *typedict; - long length; - + Py_ssize_t length; Py_ssize_t itemsize, itemalign; typedict = PyTuple_GetItem(args, 2); if (!typedict) return NULL; - proto = PyDict_GetItemString(typedict, "_length_"); /* Borrowed ref */ - if (!proto || !PyInt_Check(proto)) { + length_attr = PyDict_GetItemString(typedict, "_length_"); /* Borrowed ref */ + if (!length_attr || !_PyAnyInt_Check(length_attr)) { PyErr_SetString(PyExc_AttributeError, "class must define a '_length_' attribute, " "which must be a positive integer"); return NULL; } - length = PyInt_AS_LONG(proto); + if (PyInt_Check(length_attr)) { + length = PyInt_AS_LONG(length_attr); + } + else { + assert(PyLong_Check(length_attr)); + length = PyLong_AsSsize_t(length_attr); + if (length == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, + "The '_length_' attribute is too large"); + } + return NULL; + } + } proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */ if (!proto) { |