summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-12-04 12:38:07 +0200
committerGitHub <noreply@github.com>2018-12-04 12:38:07 +0200
commit93d7918f77278f973a4a106c1d01ad2d9805816d (patch)
treef20159e9bbab7695d6c69e42937edf48c08bfb63
parenteab421bff954e4fb77516bfe6c98d30ced1412d0 (diff)
downloadcpython-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.py7
-rw-r--r--Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst1
-rw-r--r--Modules/_ctypes/_ctypes.c24
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) {