comparison src/if_py_both.h @ 33303:924e9cb09df7 v9.0.1917

patch 9.0.1917: undefined behaviour with python function pointer Commit: https://github.com/vim/vim/commit/d606fccf6fd716bda43a8e1d11d898f438d28b82 Author: Yee Cheng Chin <ychin.git@gmail.com> Date: Wed Sep 20 19:59:47 2023 +0200 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>
author Christian Brabandt <cb@256bit.org>
date Wed, 20 Sep 2023 20:15:04 +0200
parents a43861545866
children a9f0f0eae10e
comparison
equal deleted inserted replaced
33302:e93c5a23154b 33303:924e9cb09df7
2077 hashitem_T *dii_hi; 2077 hashitem_T *dii_hi;
2078 long_u dii_todo; 2078 long_u dii_todo;
2079 } dictiterinfo_T; 2079 } dictiterinfo_T;
2080 2080
2081 static PyObject * 2081 static PyObject *
2082 DictionaryIterNext(dictiterinfo_T **dii) 2082 DictionaryIterNext(void **arg)
2083 { 2083 {
2084 PyObject *ret; 2084 PyObject *ret;
2085 dictiterinfo_T **dii = (dictiterinfo_T**)arg;
2085 2086
2086 if (!(*dii)->dii_todo) 2087 if (!(*dii)->dii_todo)
2087 return NULL; 2088 return NULL;
2088 2089
2089 if ((*dii)->dii_ht->ht_changed != (*dii)->dii_changed) 2090 if ((*dii)->dii_ht->ht_changed != (*dii)->dii_changed)
2121 dii->dii_ht = ht; 2122 dii->dii_ht = ht;
2122 dii->dii_hi = ht->ht_array; 2123 dii->dii_hi = ht->ht_array;
2123 dii->dii_todo = ht->ht_used; 2124 dii->dii_todo = ht->ht_used;
2124 2125
2125 return IterNew(dii, 2126 return IterNew(dii,
2126 (destructorfun)(void *) PyMem_Free, (nextfun) DictionaryIterNext, 2127 PyMem_Free, DictionaryIterNext,
2127 NULL, NULL, (PyObject *)self); 2128 NULL, NULL, (PyObject *)self);
2128 } 2129 }
2129 2130
2130 static int 2131 static int
2131 DictionaryAssItem( 2132 DictionaryAssItem(
3079 listwatch_T lw; 3080 listwatch_T lw;
3080 list_T *list; 3081 list_T *list;
3081 } listiterinfo_T; 3082 } listiterinfo_T;
3082 3083
3083 static void 3084 static void
3084 ListIterDestruct(listiterinfo_T *lii) 3085 ListIterDestruct(void *arg)
3085 { 3086 {
3087 listiterinfo_T *lii = (listiterinfo_T*)arg;
3086 list_rem_watch(lii->list, &lii->lw); 3088 list_rem_watch(lii->list, &lii->lw);
3087 list_unref(lii->list); 3089 list_unref(lii->list);
3088 PyMem_Free(lii); 3090 PyMem_Free(lii);
3089 } 3091 }
3090 3092
3091 static PyObject * 3093 static PyObject *
3092 ListIterNext(listiterinfo_T **lii) 3094 ListIterNext(void **arg)
3093 { 3095 {
3094 PyObject *ret; 3096 PyObject *ret;
3097 listiterinfo_T **lii = (listiterinfo_T**)arg;
3095 3098
3096 if (!((*lii)->lw.lw_item)) 3099 if (!((*lii)->lw.lw_item))
3097 return NULL; 3100 return NULL;
3098 3101
3099 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv)))) 3102 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
3121 lii->lw.lw_item = l->lv_first; 3124 lii->lw.lw_item = l->lv_first;
3122 lii->list = l; 3125 lii->list = l;
3123 ++l->lv_refcount; 3126 ++l->lv_refcount;
3124 3127
3125 return IterNew(lii, 3128 return IterNew(lii,
3126 (destructorfun) ListIterDestruct, (nextfun) ListIterNext, 3129 ListIterDestruct, ListIterNext,
3127 NULL, NULL, (PyObject *)self); 3130 NULL, NULL, (PyObject *)self);
3128 } 3131 }
3129 3132
3130 static char *ListAttrs[] = { 3133 static char *ListAttrs[] = {
3131 "locked", 3134 "locked",
3745 void *lastoption; 3748 void *lastoption;
3746 int opt_type; 3749 int opt_type;
3747 } optiterinfo_T; 3750 } optiterinfo_T;
3748 3751
3749 static PyObject * 3752 static PyObject *
3750 OptionsIterNext(optiterinfo_T **oii) 3753 OptionsIterNext(void **arg)
3751 { 3754 {
3752 char_u *name; 3755 char_u *name;
3756 optiterinfo_T **oii = (optiterinfo_T**)arg;
3753 3757
3754 if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type))) 3758 if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
3755 return PyString_FromString((char *)name); 3759 return PyString_FromString((char *)name);
3756 3760
3757 return NULL; 3761 return NULL;
3770 3774
3771 oii->opt_type = self->opt_type; 3775 oii->opt_type = self->opt_type;
3772 oii->lastoption = NULL; 3776 oii->lastoption = NULL;
3773 3777
3774 return IterNew(oii, 3778 return IterNew(oii,
3775 (destructorfun)(void *) PyMem_Free, (nextfun) OptionsIterNext, 3779 PyMem_Free, OptionsIterNext,
3776 NULL, NULL, (PyObject *)self); 3780 NULL, NULL, (PyObject *)self);
3777 } 3781 }
3778 3782
3779 static int 3783 static int
3780 set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags) 3784 set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
4147 } 4151 }
4148 4152
4149 return 0; 4153 return 0;
4150 } 4154 }
4151 4155
4156 static int
4157 CheckWindowCb(void *self)
4158 {
4159 return CheckWindow((WindowObject*)self);
4160 }
4161
4152 static PyObject * 4162 static PyObject *
4153 WindowNew(win_T *win, tabpage_T *tab) 4163 WindowNew(win_T *win, tabpage_T *tab)
4154 { 4164 {
4155 /* 4165 /*
4156 * We need to handle deletion of windows underneath us. 4166 * We need to handle deletion of windows underneath us.
4285 else if (strcmp(name, "col") == 0) 4295 else if (strcmp(name, "col") == 0)
4286 return PyLong_FromLong((long)(self->win->w_wincol)); 4296 return PyLong_FromLong((long)(self->win->w_wincol));
4287 else if (strcmp(name, "vars") == 0) 4297 else if (strcmp(name, "vars") == 0)
4288 return NEW_DICTIONARY(self->win->w_vars); 4298 return NEW_DICTIONARY(self->win->w_vars);
4289 else if (strcmp(name, "options") == 0) 4299 else if (strcmp(name, "options") == 0)
4290 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow, 4300 return OptionsNew(SREQ_WIN, self->win, CheckWindowCb,
4291 (PyObject *) self); 4301 (PyObject *) self);
4292 else if (strcmp(name, "number") == 0) 4302 else if (strcmp(name, "number") == 0)
4293 { 4303 {
4294 if (CheckTabPage(self->tabObject)) 4304 if (CheckTabPage(self->tabObject))
4295 return NULL; 4305 return NULL;
5140 } 5150 }
5141 5151
5142 return 0; 5152 return 0;
5143 } 5153 }
5144 5154
5155 static int
5156 CheckBufferCb(void *self)
5157 {
5158 return CheckBuffer((BufferObject*)self);
5159 }
5160
5145 static PyObject * 5161 static PyObject *
5146 RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end) 5162 RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
5147 { 5163 {
5148 if (CheckBuffer(self)) 5164 if (CheckBuffer(self))
5149 return NULL; 5165 return NULL;
5542 else if (strcmp(name, "number") == 0) 5558 else if (strcmp(name, "number") == 0)
5543 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum); 5559 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
5544 else if (strcmp(name, "vars") == 0) 5560 else if (strcmp(name, "vars") == 0)
5545 return NEW_DICTIONARY(self->buf->b_vars); 5561 return NEW_DICTIONARY(self->buf->b_vars);
5546 else if (strcmp(name, "options") == 0) 5562 else if (strcmp(name, "options") == 0)
5547 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer, 5563 return OptionsNew(SREQ_BUF, self->buf, CheckBufferCb,
5548 (PyObject *) self); 5564 (PyObject *) self);
5549 else if (strcmp(name, "__members__") == 0) 5565 else if (strcmp(name, "__members__") == 0)
5550 return ObjectDir(NULL, BufferAttrs); 5566 return ObjectDir(NULL, BufferAttrs);
5551 else 5567 else
5552 return NULL; 5568 return NULL;
5740 return NULL; 5756 return NULL;
5741 } 5757 }
5742 } 5758 }
5743 5759
5744 static void 5760 static void
5745 BufMapIterDestruct(PyObject *buffer) 5761 BufMapIterDestruct(void* arg)
5746 { 5762 {
5763 PyObject *buffer = (PyObject*)arg;
5747 // Iteration was stopped before all buffers were processed 5764 // Iteration was stopped before all buffers were processed
5748 if (buffer) 5765 if (buffer)
5749 { 5766 {
5750 Py_DECREF(buffer); 5767 Py_DECREF(buffer);
5751 } 5768 }
5752 } 5769 }
5753 5770
5754 static int 5771 static int
5755 BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg) 5772 BufMapIterTraverse(void *iter, visitproc visit, void *arg)
5756 { 5773 {
5774 PyObject *buffer = (PyObject*)iter;
5757 if (buffer) 5775 if (buffer)
5758 Py_VISIT(buffer); 5776 Py_VISIT(buffer);
5759 return 0; 5777 return 0;
5760 } 5778 }
5761 5779
5762 static int 5780 static int
5763 BufMapIterClear(PyObject **buffer) 5781 BufMapIterClear(void **iter)
5764 { 5782 {
5783 PyObject **buffer = (PyObject**)iter;
5765 if (*buffer) 5784 if (*buffer)
5766 Py_CLEAR(*buffer); 5785 Py_CLEAR(*buffer);
5767 return 0; 5786 return 0;
5768 } 5787 }
5769 5788
5770 static PyObject * 5789 static PyObject *
5771 BufMapIterNext(PyObject **buffer) 5790 BufMapIterNext(void **arg)
5772 { 5791 {
5773 PyObject *next; 5792 PyObject *next;
5774 PyObject *ret; 5793 PyObject *ret;
5794 PyObject **buffer = (PyObject**)arg;
5775 5795
5776 if (!*buffer) 5796 if (!*buffer)
5777 return NULL; 5797 return NULL;
5778 5798
5779 ret = *buffer; 5799 ret = *buffer;
5799 { 5819 {
5800 PyObject *buffer; 5820 PyObject *buffer;
5801 5821
5802 buffer = BufferNew(firstbuf); 5822 buffer = BufferNew(firstbuf);
5803 return IterNew(buffer, 5823 return IterNew(buffer,
5804 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext, 5824 BufMapIterDestruct, BufMapIterNext,
5805 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear, 5825 BufMapIterTraverse, BufMapIterClear,
5806 (PyObject *)self); 5826 (PyObject *)self);
5807 } 5827 }
5808 5828
5809 static PyMappingMethods BufMapAsMapping = { 5829 static PyMappingMethods BufMapAsMapping = {
5810 (lenfunc) BufMapLength, 5830 (lenfunc) BufMapLength,
6122 check_cursor(); 6142 check_cursor();
6123 update_curbuf(UPD_NOT_VALID); 6143 update_curbuf(UPD_NOT_VALID);
6124 } 6144 }
6125 6145
6126 static void 6146 static void
6127 run_eval(const char *cmd, typval_T *rettv 6147 run_eval(const char *cmd, void *arg
6128 #ifdef PY_CAN_RECURSE 6148 #ifdef PY_CAN_RECURSE
6129 , PyGILState_STATE *pygilstate UNUSED 6149 , PyGILState_STATE *pygilstate UNUSED
6130 #endif 6150 #endif
6131 ) 6151 )
6132 { 6152 {
6133 PyObject *run_ret; 6153 PyObject *run_ret;
6154 typval_T *rettv = (typval_T*)arg;
6134 6155
6135 run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals); 6156 run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
6136 if (run_ret == NULL) 6157 if (run_ret == NULL)
6137 { 6158 {
6138 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit)) 6159 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))