mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 9.0.1917: undefined behaviour with python function pointer
Problem: undefined behaviour with python function pointer Solution: correctly cast function pointers from void Fix more undefined behaviors in if_python Fix remaining UBSAN errors from Clang 17 in if_python in casting function pointers. Also fix a mistake where `PyMem_Free()` should be returning void, by the dynamic build is mistakenly casting it as a function that returns an int. closes: #13128 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
committed by
Christian Brabandt
parent
aa64ba1587
commit
d606fccf6f
@@ -2079,9 +2079,10 @@ typedef struct
|
|||||||
} dictiterinfo_T;
|
} dictiterinfo_T;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
DictionaryIterNext(dictiterinfo_T **dii)
|
DictionaryIterNext(void **arg)
|
||||||
{
|
{
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
|
dictiterinfo_T **dii = (dictiterinfo_T**)arg;
|
||||||
|
|
||||||
if (!(*dii)->dii_todo)
|
if (!(*dii)->dii_todo)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2123,7 +2124,7 @@ DictionaryIter(DictionaryObject *self)
|
|||||||
dii->dii_todo = ht->ht_used;
|
dii->dii_todo = ht->ht_used;
|
||||||
|
|
||||||
return IterNew(dii,
|
return IterNew(dii,
|
||||||
(destructorfun)(void *) PyMem_Free, (nextfun) DictionaryIterNext,
|
PyMem_Free, DictionaryIterNext,
|
||||||
NULL, NULL, (PyObject *)self);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3081,17 +3082,19 @@ typedef struct
|
|||||||
} listiterinfo_T;
|
} listiterinfo_T;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ListIterDestruct(listiterinfo_T *lii)
|
ListIterDestruct(void *arg)
|
||||||
{
|
{
|
||||||
|
listiterinfo_T *lii = (listiterinfo_T*)arg;
|
||||||
list_rem_watch(lii->list, &lii->lw);
|
list_rem_watch(lii->list, &lii->lw);
|
||||||
list_unref(lii->list);
|
list_unref(lii->list);
|
||||||
PyMem_Free(lii);
|
PyMem_Free(lii);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
ListIterNext(listiterinfo_T **lii)
|
ListIterNext(void **arg)
|
||||||
{
|
{
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
|
listiterinfo_T **lii = (listiterinfo_T**)arg;
|
||||||
|
|
||||||
if (!((*lii)->lw.lw_item))
|
if (!((*lii)->lw.lw_item))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -3123,7 +3126,7 @@ ListIter(ListObject *self)
|
|||||||
++l->lv_refcount;
|
++l->lv_refcount;
|
||||||
|
|
||||||
return IterNew(lii,
|
return IterNew(lii,
|
||||||
(destructorfun) ListIterDestruct, (nextfun) ListIterNext,
|
ListIterDestruct, ListIterNext,
|
||||||
NULL, NULL, (PyObject *)self);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3747,9 +3750,10 @@ typedef struct
|
|||||||
} optiterinfo_T;
|
} optiterinfo_T;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
OptionsIterNext(optiterinfo_T **oii)
|
OptionsIterNext(void **arg)
|
||||||
{
|
{
|
||||||
char_u *name;
|
char_u *name;
|
||||||
|
optiterinfo_T **oii = (optiterinfo_T**)arg;
|
||||||
|
|
||||||
if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
|
if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
|
||||||
return PyString_FromString((char *)name);
|
return PyString_FromString((char *)name);
|
||||||
@@ -3772,7 +3776,7 @@ OptionsIter(OptionsObject *self)
|
|||||||
oii->lastoption = NULL;
|
oii->lastoption = NULL;
|
||||||
|
|
||||||
return IterNew(oii,
|
return IterNew(oii,
|
||||||
(destructorfun)(void *) PyMem_Free, (nextfun) OptionsIterNext,
|
PyMem_Free, OptionsIterNext,
|
||||||
NULL, NULL, (PyObject *)self);
|
NULL, NULL, (PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4149,6 +4153,12 @@ CheckWindow(WindowObject *self)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CheckWindowCb(void *self)
|
||||||
|
{
|
||||||
|
return CheckWindow((WindowObject*)self);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
WindowNew(win_T *win, tabpage_T *tab)
|
WindowNew(win_T *win, tabpage_T *tab)
|
||||||
{
|
{
|
||||||
@@ -4287,7 +4297,7 @@ WindowAttr(WindowObject *self, char *name)
|
|||||||
else if (strcmp(name, "vars") == 0)
|
else if (strcmp(name, "vars") == 0)
|
||||||
return NEW_DICTIONARY(self->win->w_vars);
|
return NEW_DICTIONARY(self->win->w_vars);
|
||||||
else if (strcmp(name, "options") == 0)
|
else if (strcmp(name, "options") == 0)
|
||||||
return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
|
return OptionsNew(SREQ_WIN, self->win, CheckWindowCb,
|
||||||
(PyObject *) self);
|
(PyObject *) self);
|
||||||
else if (strcmp(name, "number") == 0)
|
else if (strcmp(name, "number") == 0)
|
||||||
{
|
{
|
||||||
@@ -5142,6 +5152,12 @@ CheckBuffer(BufferObject *self)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CheckBufferCb(void *self)
|
||||||
|
{
|
||||||
|
return CheckBuffer((BufferObject*)self);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
|
RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
|
||||||
{
|
{
|
||||||
@@ -5544,7 +5560,7 @@ BufferAttr(BufferObject *self, char *name)
|
|||||||
else if (strcmp(name, "vars") == 0)
|
else if (strcmp(name, "vars") == 0)
|
||||||
return NEW_DICTIONARY(self->buf->b_vars);
|
return NEW_DICTIONARY(self->buf->b_vars);
|
||||||
else if (strcmp(name, "options") == 0)
|
else if (strcmp(name, "options") == 0)
|
||||||
return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
|
return OptionsNew(SREQ_BUF, self->buf, CheckBufferCb,
|
||||||
(PyObject *) self);
|
(PyObject *) self);
|
||||||
else if (strcmp(name, "__members__") == 0)
|
else if (strcmp(name, "__members__") == 0)
|
||||||
return ObjectDir(NULL, BufferAttrs);
|
return ObjectDir(NULL, BufferAttrs);
|
||||||
@@ -5742,8 +5758,9 @@ BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BufMapIterDestruct(PyObject *buffer)
|
BufMapIterDestruct(void* arg)
|
||||||
{
|
{
|
||||||
|
PyObject *buffer = (PyObject*)arg;
|
||||||
// Iteration was stopped before all buffers were processed
|
// Iteration was stopped before all buffers were processed
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
@@ -5752,26 +5769,29 @@ BufMapIterDestruct(PyObject *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
|
BufMapIterTraverse(void *iter, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
|
PyObject *buffer = (PyObject*)iter;
|
||||||
if (buffer)
|
if (buffer)
|
||||||
Py_VISIT(buffer);
|
Py_VISIT(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
BufMapIterClear(PyObject **buffer)
|
BufMapIterClear(void **iter)
|
||||||
{
|
{
|
||||||
|
PyObject **buffer = (PyObject**)iter;
|
||||||
if (*buffer)
|
if (*buffer)
|
||||||
Py_CLEAR(*buffer);
|
Py_CLEAR(*buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
BufMapIterNext(PyObject **buffer)
|
BufMapIterNext(void **arg)
|
||||||
{
|
{
|
||||||
PyObject *next;
|
PyObject *next;
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
|
PyObject **buffer = (PyObject**)arg;
|
||||||
|
|
||||||
if (!*buffer)
|
if (!*buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -5801,8 +5821,8 @@ BufMapIter(PyObject *self)
|
|||||||
|
|
||||||
buffer = BufferNew(firstbuf);
|
buffer = BufferNew(firstbuf);
|
||||||
return IterNew(buffer,
|
return IterNew(buffer,
|
||||||
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
|
BufMapIterDestruct, BufMapIterNext,
|
||||||
(traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear,
|
BufMapIterTraverse, BufMapIterClear,
|
||||||
(PyObject *)self);
|
(PyObject *)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6124,13 +6144,14 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_eval(const char *cmd, typval_T *rettv
|
run_eval(const char *cmd, void *arg
|
||||||
#ifdef PY_CAN_RECURSE
|
#ifdef PY_CAN_RECURSE
|
||||||
, PyGILState_STATE *pygilstate UNUSED
|
, PyGILState_STATE *pygilstate UNUSED
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PyObject *run_ret;
|
PyObject *run_ret;
|
||||||
|
typval_T *rettv = (typval_T*)arg;
|
||||||
|
|
||||||
run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
|
run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
|
||||||
if (run_ret == NULL)
|
if (run_ret == NULL)
|
||||||
|
@@ -317,7 +317,7 @@ struct PyMethodDef { Py_ssize_t a; };
|
|||||||
*/
|
*/
|
||||||
static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
|
static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
|
||||||
static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
|
static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
|
||||||
static int(*dll_PyMem_Free)(void *);
|
static void(*dll_PyMem_Free)(void *);
|
||||||
static void* (*dll_PyMem_Malloc)(size_t);
|
static void* (*dll_PyMem_Malloc)(size_t);
|
||||||
static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
|
static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
|
||||||
static int(*dll_PyErr_BadArgument)(void);
|
static int(*dll_PyErr_BadArgument)(void);
|
||||||
|
@@ -442,7 +442,7 @@ static void(*py3_PyEval_RestoreThread)(PyThreadState *);
|
|||||||
static PyThreadState*(*py3_PyEval_SaveThread)(void);
|
static PyThreadState*(*py3_PyEval_SaveThread)(void);
|
||||||
static int (*py3_PyArg_Parse)(PyObject *, char *, ...);
|
static int (*py3_PyArg_Parse)(PyObject *, char *, ...);
|
||||||
static int (*py3_PyArg_ParseTuple)(PyObject *, char *, ...);
|
static int (*py3_PyArg_ParseTuple)(PyObject *, char *, ...);
|
||||||
static int (*py3_PyMem_Free)(void *);
|
static void (*py3_PyMem_Free)(void *);
|
||||||
static void* (*py3_PyMem_Malloc)(size_t);
|
static void* (*py3_PyMem_Malloc)(size_t);
|
||||||
static int (*py3_Py_IsInitialized)(void);
|
static int (*py3_Py_IsInitialized)(void);
|
||||||
static void (*py3_PyErr_Clear)(void);
|
static void (*py3_PyErr_Clear)(void);
|
||||||
|
@@ -699,6 +699,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1917,
|
||||||
/**/
|
/**/
|
||||||
1916,
|
1916,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user