]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[2.7] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006). (GH-7441)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 4 Dec 2018 10:38:07 +0000 (12:38 +0200)
committerGitHub <noreply@github.com>
Tue, 4 Dec 2018 10:38:07 +0000 (12:38 +0200)
(cherry picked from commit 735abadd5bd91db4a9e6f4311969b0afacca0a1a)

Co-Authored-By: Segev Finer <segev208@gmail.com>
Lib/ctypes/test/test_arrays.py
Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst [new file with mode: 0644]
Modules/_ctypes/_ctypes.c

index 49aaab52b93b49384a5de35849cfa071edd82ed6..53859a3e5e9394e8cd4b787495f5334cc6a0e6d4 100644 (file)
@@ -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 (file)
index 0000000..afaff73
--- /dev/null
@@ -0,0 +1 @@
+Support arrays >=2GiB in :mod:`ctypes`.  Patch by Segev Finer.
index fabbdf13e940a9566a20cba265b90762b5a0418f..9b289af91be7776e64c7d1ec78d288de2d5ee4c5 100644 (file)
@@ -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) {