mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
bpo-46323: _ctypes.CFuncPtr fails if _argtypes_ is too long (GH-31188)
ctypes.CFUNCTYPE() and ctypes.WINFUNCTYPE() now fail to create the type if its "_argtypes_" member contains too many arguments. Previously, the error was only raised when calling a function. Change also how CFUNCTYPE() and WINFUNCTYPE() handle KeyError to prevent creating a chain of exceptions if ctypes.CFuncPtr raises an error.
This commit is contained in:
parent
8e98175a03
commit
4cce1352bb
6 changed files with 45 additions and 22 deletions
|
|
@ -92,15 +92,18 @@ def CFUNCTYPE(restype, *argtypes, **kw):
|
|||
flags |= _FUNCFLAG_USE_LASTERROR
|
||||
if kw:
|
||||
raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
|
||||
|
||||
try:
|
||||
return _c_functype_cache[(restype, argtypes, flags)]
|
||||
except KeyError:
|
||||
class CFunctionType(_CFuncPtr):
|
||||
_argtypes_ = argtypes
|
||||
_restype_ = restype
|
||||
_flags_ = flags
|
||||
_c_functype_cache[(restype, argtypes, flags)] = CFunctionType
|
||||
return CFunctionType
|
||||
pass
|
||||
|
||||
class CFunctionType(_CFuncPtr):
|
||||
_argtypes_ = argtypes
|
||||
_restype_ = restype
|
||||
_flags_ = flags
|
||||
_c_functype_cache[(restype, argtypes, flags)] = CFunctionType
|
||||
return CFunctionType
|
||||
|
||||
if _os.name == "nt":
|
||||
from _ctypes import LoadLibrary as _dlopen
|
||||
|
|
@ -116,15 +119,18 @@ if _os.name == "nt":
|
|||
flags |= _FUNCFLAG_USE_LASTERROR
|
||||
if kw:
|
||||
raise ValueError("unexpected keyword argument(s) %s" % kw.keys())
|
||||
|
||||
try:
|
||||
return _win_functype_cache[(restype, argtypes, flags)]
|
||||
except KeyError:
|
||||
class WinFunctionType(_CFuncPtr):
|
||||
_argtypes_ = argtypes
|
||||
_restype_ = restype
|
||||
_flags_ = flags
|
||||
_win_functype_cache[(restype, argtypes, flags)] = WinFunctionType
|
||||
return WinFunctionType
|
||||
pass
|
||||
|
||||
class WinFunctionType(_CFuncPtr):
|
||||
_argtypes_ = argtypes
|
||||
_restype_ = restype
|
||||
_flags_ = flags
|
||||
_win_functype_cache[(restype, argtypes, flags)] = WinFunctionType
|
||||
return WinFunctionType
|
||||
if WINFUNCTYPE.__doc__:
|
||||
WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
|
||||
|
||||
|
|
|
|||
|
|
@ -294,15 +294,22 @@ class SampleCallbacksTestCase(unittest.TestCase):
|
|||
return len(args)
|
||||
|
||||
CTYPES_MAX_ARGCOUNT = 1024
|
||||
|
||||
# valid call with nargs <= CTYPES_MAX_ARGCOUNT
|
||||
proto = CFUNCTYPE(c_int, *(c_int,) * CTYPES_MAX_ARGCOUNT)
|
||||
cb = proto(func)
|
||||
args1 = (1,) * CTYPES_MAX_ARGCOUNT
|
||||
self.assertEqual(cb(*args1), CTYPES_MAX_ARGCOUNT)
|
||||
|
||||
# invalid call with nargs > CTYPES_MAX_ARGCOUNT
|
||||
args2 = (1,) * (CTYPES_MAX_ARGCOUNT + 1)
|
||||
with self.assertRaises(ArgumentError):
|
||||
cb(*args2)
|
||||
|
||||
# error when creating the type with too many arguments
|
||||
with self.assertRaises(ArgumentError):
|
||||
CFUNCTYPE(c_int, *(c_int,) * (CTYPES_MAX_ARGCOUNT + 1))
|
||||
|
||||
def test_convert_result_error(self):
|
||||
def func():
|
||||
return ("tuple",)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue