Skip to content

Commit 5dbb4ae

Browse files
committed
pythongh-46376: add (failing) tests for ctypes/pointer/cast/set_contents
Previous attempt to fix pythongh-46376 was incomplete and overall it didn't succeed, and was reverted in 3.11. However, we have discovered some dangerous issues with ctypes, that aren't fixed or documented anywhere. This commit adds tests (@expectedfailure) so at least developers are aware of situations where memory might be corrupted, leaked or when changing a pointer value might have no effect. Hopefully, we should be able to remove @expectedfailure in the future, with new shiny ctypes implementation or at least a bugfix.
1 parent fecb9fa commit 5dbb4ae

File tree

6 files changed

+421
-57
lines changed

6 files changed

+421
-57
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ Tools/unicode/data/
124124
/config.status.lineno
125125
# hendrikmuhs/ccache-action@v1
126126
/.ccache
127+
# clangd and it's debugger
128+
/.cache
127129
/platform
128130
/profile-clean-stamp
129131
/profile-run-stamp

Lib/test/test_ctypes/test_arrays.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import gc
12
import ctypes
23
import sys
34
import unittest
45
import warnings
5-
from ctypes import (Structure, Array, sizeof, addressof,
6+
import weakref
7+
from ctypes import (Structure, Array, sizeof, addressof, POINTER, pointer,
68
create_string_buffer, create_unicode_buffer,
79
c_char, c_wchar, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
810
c_long, c_ulonglong, c_float, c_double, c_longdouble)
@@ -249,6 +251,32 @@ def test_deprecation(self):
249251
with self.assertWarns(DeprecationWarning):
250252
CharArray = ctypes.ARRAY(c_char, 3)
251253

254+
def test_ptr_reuse(self):
255+
w = weakref.WeakValueDictionary()
256+
arr = 3 * POINTER(c_short)
257+
258+
vals = arr(
259+
pointer(w.setdefault(10, c_short(10))),
260+
pointer(w.setdefault(11, c_short(11))),
261+
None,
262+
)
263+
gc.collect()
264+
265+
self.assertEqual(vals[0].contents.value, 10)
266+
self.assertEqual(vals[1].contents.value, 11)
267+
268+
vals[2] = vals[0]
269+
270+
self.assertEqual(vals[2].contents.value, 10)
271+
272+
vals[2][0] = w.setdefault(12, c_short(12))
273+
vals[2].contents = w.setdefault(13, c_short(13))
274+
275+
gc.collect()
276+
277+
self.assertEqual(vals[2].contents.value, 13)
278+
self.assertEqual(vals[0].contents.value, 12)
279+
252280

253281
if __name__ == '__main__':
254282
unittest.main()

0 commit comments

Comments
 (0)