mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
[3.14] gh-138008: Fix segfaults in _ctypes due to invalid argtypes (GH-138285) (GH-138742)
(cherry picked from commit 1ce05537a3)
Signed-off-by: Nguyen Viet Dung <29406816+magnified103@users.noreply.github.com>
Co-authored-by: Yongzi Li <204532581+Yzi-Li@users.noreply.github.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
This commit is contained in:
parent
7aab50cd7a
commit
d7500f6078
3 changed files with 49 additions and 11 deletions
|
|
@ -72,6 +72,32 @@ def test_paramflags(self):
|
|||
self.assertEqual(func(None), None)
|
||||
self.assertEqual(func(input=None), None)
|
||||
|
||||
def test_invalid_paramflags(self):
|
||||
proto = CFUNCTYPE(c_int, c_char_p)
|
||||
with self.assertRaises(ValueError):
|
||||
func = proto(("myprintf", testdll), ((1, "fmt"), (1, "arg1")))
|
||||
|
||||
def test_invalid_setattr_argtypes(self):
|
||||
proto = CFUNCTYPE(c_int, c_char_p)
|
||||
func = proto(("myprintf", testdll), ((1, "fmt"),))
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "_argtypes_ must be a sequence of types"):
|
||||
func.argtypes = 123
|
||||
self.assertEqual(func.argtypes, (c_char_p,))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "paramflags must have the same length as argtypes"):
|
||||
func.argtypes = (c_char_p, c_int)
|
||||
self.assertEqual(func.argtypes, (c_char_p,))
|
||||
|
||||
def test_paramflags_outarg(self):
|
||||
proto = CFUNCTYPE(c_int, c_char_p, c_int)
|
||||
with self.assertRaisesRegex(TypeError, "must be a pointer type"):
|
||||
func = proto(("myprintf", testdll), ((1, "fmt"), (2, "out")))
|
||||
|
||||
proto = CFUNCTYPE(c_int, c_char_p, c_void_p)
|
||||
func = proto(("myprintf", testdll), ((1, "fmt"), (2, "out")))
|
||||
with self.assertRaisesRegex(TypeError, "must be a pointer type"):
|
||||
func.argtypes = (c_char_p, c_int)
|
||||
|
||||
def test_int_pointer_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Fix segmentation faults in the :mod:`ctypes` module due to invalid :attr:`~ctypes._CFuncPtr.argtypes`. Patch by Dung Nguyen.
|
||||
|
|
@ -3628,6 +3628,9 @@ atomic_xgetref(PyObject *obj, PyObject **field)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
_validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags, PyObject *argtypes);
|
||||
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
|
|
@ -3741,16 +3744,22 @@ static int
|
|||
_ctypes_CFuncPtr_argtypes_set_impl(PyCFuncPtrObject *self, PyObject *value)
|
||||
/*[clinic end generated code: output=596a36e2ae89d7d1 input=c4627573e980aa8b]*/
|
||||
{
|
||||
PyObject *converters;
|
||||
|
||||
if (value == NULL || value == Py_None) {
|
||||
atomic_xsetref(&self->argtypes, NULL);
|
||||
atomic_xsetref(&self->converters, NULL);
|
||||
} else {
|
||||
ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self)));
|
||||
converters = converters_from_argtypes(st, value);
|
||||
PyTypeObject *type = Py_TYPE(self);
|
||||
ctypes_state *st = get_module_state_by_def(Py_TYPE(type));
|
||||
|
||||
PyObject *converters = converters_from_argtypes(st, value);
|
||||
if (!converters)
|
||||
return -1;
|
||||
|
||||
/* Verify paramflags again due to constraints with argtypes */
|
||||
if (!_validate_paramflags(st, type, self->paramflags, value)) {
|
||||
Py_DECREF(converters);
|
||||
return -1;
|
||||
}
|
||||
atomic_xsetref(&self->converters, converters);
|
||||
Py_INCREF(value);
|
||||
atomic_xsetref(&self->argtypes, value);
|
||||
|
|
@ -3880,10 +3889,9 @@ _check_outarg_type(ctypes_state *st, PyObject *arg, Py_ssize_t index)
|
|||
|
||||
/* Returns 1 on success, 0 on error */
|
||||
static int
|
||||
_validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags)
|
||||
_validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags, PyObject *argtypes)
|
||||
{
|
||||
Py_ssize_t i, len;
|
||||
PyObject *argtypes;
|
||||
|
||||
StgInfo *info;
|
||||
if (PyStgInfo_FromType(st, (PyObject *)type, &info) < 0) {
|
||||
|
|
@ -3894,10 +3902,13 @@ _validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags)
|
|||
"abstract class");
|
||||
return 0;
|
||||
}
|
||||
argtypes = info->argtypes;
|
||||
if (argtypes == NULL) {
|
||||
argtypes = info->argtypes;
|
||||
}
|
||||
|
||||
if (paramflags == NULL || info->argtypes == NULL)
|
||||
if (paramflags == NULL || argtypes == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!PyTuple_Check(paramflags)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
|
@ -3906,7 +3917,7 @@ _validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags)
|
|||
}
|
||||
|
||||
len = PyTuple_GET_SIZE(paramflags);
|
||||
if (len != PyTuple_GET_SIZE(info->argtypes)) {
|
||||
if (len != PyTuple_GET_SIZE(argtypes)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"paramflags must have the same length as argtypes");
|
||||
return 0;
|
||||
|
|
@ -4082,7 +4093,7 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
#endif
|
||||
#undef USE_DLERROR
|
||||
ctypes_state *st = get_module_state_by_def(Py_TYPE(type));
|
||||
if (!_validate_paramflags(st, type, paramflags)) {
|
||||
if (!_validate_paramflags(st, type, paramflags, NULL)) {
|
||||
Py_DECREF(ftuple);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -4126,7 +4137,7 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
paramflags = NULL;
|
||||
|
||||
ctypes_state *st = get_module_state_by_def(Py_TYPE(type));
|
||||
if (!_validate_paramflags(st, type, paramflags)) {
|
||||
if (!_validate_paramflags(st, type, paramflags, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
self = (PyCFuncPtrObject *)generic_pycdata_new(st, type, args, kwds);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue