From 93d7918f77278f973a4a106c1d01ad2d9805816d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 4 Dec 2018 12:38:07 +0200 Subject: [2.7] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006). (GH-7441) (cherry picked from commit 735abadd5bd91db4a9e6f4311969b0afacca0a1a) Co-Authored-By: Segev Finer --- Lib/ctypes/test/test_arrays.py | 7 +++++++ .../2017-09-29-16-40-38.bpo-16865.l-f6I_.rst | 1 + Modules/_ctypes/_ctypes.c | 24 ++++++++++++++++------ 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst 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) { -- cgit v1.2.1