Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Lib/test/test_ctypes/test_pointers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import gc
import sys
import unittest
import os
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import can be removed with my proposed code.

from ctypes import (CDLL, CFUNCTYPE, Structure,
POINTER, pointer, _Pointer,
byref, sizeof,
Expand Down Expand Up @@ -472,6 +473,23 @@ class C(Structure):
ptr.set_type(c_int)
self.assertIs(ptr._type_, c_int)

class TestPointerStringProto(unittest.TestCase):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to add the test to the end of PointersTestCase, instead of adding a new test case.

def test_pointer_string_proto_argtypes_error(self):
with self.assertWarns(DeprecationWarning):
BadType = ctypes.POINTER("BugTrigger")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to avoid deprecated code path. You should be able to use:

Suggested change
with self.assertWarns(DeprecationWarning):
BadType = ctypes.POINTER("BugTrigger")
class BadType(ctypes._Pointer):
# _type_ is not defined on purpose
pass


if os.name == "nt":
libc = ctypes.WinDLL("kernel32.dll")
func = libc.GetCurrentProcessId
else:
libc = ctypes.CDLL(None)
func = libc.getpid

func.argtypes = (BadType,)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the Python C API:

Suggested change
if os.name == "nt":
libc = ctypes.WinDLL("kernel32.dll")
func = libc.GetCurrentProcessId
else:
libc = ctypes.CDLL(None)
func = libc.getpid
func.argtypes = (BadType,)
func = ctypes.pythonapi.Py_GetVersion
func.argtypes = (BadType,)


with self.assertRaises(ctypes.ArgumentError):
func(ctypes.byref(ctypes.c_int(0)))


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fixed a crash in ctypes when using a deprecated ``POINTER(str)`` type in
``argtypes``. Instead of aborting, ctypes now raises a proper Python
exception when the pointer target type is unresolved.
8 changes: 7 additions & 1 deletion Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,13 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls,
/* If we expect POINTER(<type>), but receive a <type> instance, accept
it by calling byref(<type>).
*/
assert(typeinfo->proto);
if(typeinfo->proto == NULL){
Comment thread
VanshAgarwal24036 marked this conversation as resolved.
Outdated
PyErr_SetString(
PyExc_TypeError,
"cannot convert argument: POINTER target type is unresolved"
Comment thread
VanshAgarwal24036 marked this conversation as resolved.
Outdated
);
return NULL;
}
switch (PyObject_IsInstance(value, typeinfo->proto)) {
case 1:
Py_INCREF(value); /* _byref steals a refcount */
Expand Down
Loading