mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-138008: Fix segfaults in _ctypes due to invalid argtypes (GH-138285)
Signed-off-by: Nguyen Viet Dung <29406816+magnified103@users.noreply.github.com> Signed-off-by: Nguyen Viet Dung <dung@ekluster.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Yongzi Li <204532581+Yzi-Li@users.noreply.github.com>
This commit is contained in:
parent
d54b1091d4
commit
1ce05537a3
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.
|
||||
|
|
@ -3634,6 +3634,9 @@ atomic_xgetref(PyObject *obj, PyObject **field)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
_validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags, PyObject *argtypes);
|
||||
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
|
|
@ -3747,16 +3750,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);
|
||||
|
|
@ -3886,10 +3895,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) {
|
||||
|
|
@ -3900,10 +3908,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,
|
||||
|
|
@ -3912,7 +3923,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;
|
||||
|
|
@ -4088,7 +4099,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;
|
||||
}
|
||||
|
|
@ -4132,7 +4143,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