0
0
mirror of https://github.com/vim/vim.git synced 2025-09-04 21:33:48 -04:00

updated for version 7.3.1056

Problem:    Python: possible memory leaks.
Solution:   Python patch 15. (ZyX) Fix will follow later.
This commit is contained in:
Bram Moolenaar 2013-05-30 12:14:49 +02:00
parent bad704fa04
commit 9bb77d6fe6
4 changed files with 102 additions and 48 deletions

View File

@ -412,7 +412,6 @@ static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int rettv_list_alloc __ARGS((typval_T *rettv)); static int rettv_list_alloc __ARGS((typval_T *rettv));
static void listitem_free __ARGS((listitem_T *item));
static long list_len __ARGS((list_T *l)); static long list_len __ARGS((list_T *l));
static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive)); static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive));
static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive)); static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
@ -428,7 +427,6 @@ static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int ec
static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID)); static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
static int free_unref_items __ARGS((int copyID)); static int free_unref_items __ARGS((int copyID));
static int rettv_dict_alloc __ARGS((typval_T *rettv)); static int rettv_dict_alloc __ARGS((typval_T *rettv));
static void dict_free __ARGS((dict_T *d, int recurse));
static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID)); static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
@ -5955,7 +5953,7 @@ listitem_alloc()
/* /*
* Free a list item. Also clears the value. Does not notify watchers. * Free a list item. Also clears the value. Does not notify watchers.
*/ */
static void void
listitem_free(item) listitem_free(item)
listitem_T *item; listitem_T *item;
{ {
@ -7031,7 +7029,7 @@ dict_unref(d)
* Free a Dictionary, including all items it contains. * Free a Dictionary, including all items it contains.
* Ignores the reference count. * Ignores the reference count.
*/ */
static void void
dict_free(d, recurse) dict_free(d, recurse)
dict_T *d; dict_T *d;
int recurse; /* Free Lists and Dictionaries recursively. */ int recurse; /* Free Lists and Dictionaries recursively. */
@ -8353,7 +8351,7 @@ get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
/* /*
* Call a function with its resolved parameters * Call a function with its resolved parameters
* Return OK when the function can't be called, FAIL otherwise. * Return FAIL when the function can't be called, OK otherwise.
* Also returns OK when an error was encountered while executing the function. * Also returns OK when an error was encountered while executing the function.
*/ */
static int static int

View File

@ -32,8 +32,15 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#define DICTKEY_DECL \ #define DICTKEY_DECL \
PyObject *dictkey_todecref; PyObject *dictkey_todecref;
#define DICTKEY_CHECK_EMPTY(err) \
if (*key == NUL) \
{ \
PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
return err; \
}
#define DICTKEY_SET_KEY (key = StringToChars(keyObject, &dictkey_todecref))
#define DICTKEY_GET(err, decref) \ #define DICTKEY_GET(err, decref) \
if (!(key = StringToChars(keyObject, &dictkey_todecref))) \ if (!DICTKEY_SET_KEY) \
{ \ { \
if (decref) \ if (decref) \
{ \ { \
@ -43,11 +50,7 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
} \ } \
if (decref && !dictkey_todecref) \ if (decref && !dictkey_todecref) \
dictkey_todecref = keyObject; \ dictkey_todecref = keyObject; \
if (*key == NUL) \ DICTKEY_CHECK_EMPTY(err)
{ \
PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
return err; \
}
#define DICTKEY_UNREF \ #define DICTKEY_UNREF \
Py_XDECREF(dictkey_todecref); Py_XDECREF(dictkey_todecref);
@ -651,9 +654,13 @@ VimEval(PyObject *self UNUSED, PyObject *args)
/* Convert the Vim type into a Python type. Create a dictionary that's /* Convert the Vim type into a Python type. Create a dictionary that's
* used to check for recursive loops. */ * used to check for recursive loops. */
lookup_dict = PyDict_New(); if (!(lookup_dict = PyDict_New()))
result = VimToPython(our_tv, 1, lookup_dict); result = NULL;
Py_DECREF(lookup_dict); else
{
result = VimToPython(our_tv, 1, lookup_dict);
Py_DECREF(lookup_dict);
}
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
@ -1401,7 +1408,9 @@ ListConcatInPlace(ListObject *self, PyObject *obj)
return NULL; return NULL;
} }
lookup_dict = PyDict_New(); if (!(lookup_dict = PyDict_New()))
return NULL;
if (list_py_concat(l, obj, lookup_dict) == -1) if (list_py_concat(l, obj, lookup_dict) == -1)
{ {
Py_DECREF(lookup_dict); Py_DECREF(lookup_dict);
@ -4023,12 +4032,8 @@ pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
PyObject *valObject; PyObject *valObject;
Py_ssize_t iter = 0; Py_ssize_t iter = 0;
dict = dict_alloc(); if (!(dict = dict_alloc()))
if (dict == NULL)
{
PyErr_NoMemory();
return -1; return -1;
}
tv->v_type = VAR_DICT; tv->v_type = VAR_DICT;
tv->vval.v_dict = dict; tv->vval.v_dict = dict;
@ -4038,9 +4043,17 @@ pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
DICTKEY_DECL DICTKEY_DECL
if (keyObject == NULL || valObject == NULL) if (keyObject == NULL || valObject == NULL)
{
dict_unref(dict);
return -1; return -1;
}
DICTKEY_GET(-1, 0) if (!DICTKEY_SET_KEY)
{
dict_unref(dict);
return -1;
}
DICTKEY_CHECK_EMPTY(-1)
di = dictitem_alloc(key); di = dictitem_alloc(key);
@ -4049,6 +4062,7 @@ pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (di == NULL) if (di == NULL)
{ {
PyErr_NoMemory(); PyErr_NoMemory();
dict_unref(dict);
return -1; return -1;
} }
di->di_tv.v_lock = 0; di->di_tv.v_lock = 0;
@ -4056,6 +4070,7 @@ pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1) if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
{ {
vim_free(di); vim_free(di);
dict_unref(dict);
return -1; return -1;
} }
@ -4063,10 +4078,13 @@ pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
{ {
clear_tv(&di->di_tv); clear_tv(&di->di_tv);
vim_free(di); vim_free(di);
dict_unref(dict);
PyErr_SetVim(_("failed to add key to dictionary")); PyErr_SetVim(_("failed to add key to dictionary"));
return -1; return -1;
} }
} }
--dict->dv_refcount;
return 0; return 0;
} }
@ -4082,19 +4100,18 @@ pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
PyObject *valObject; PyObject *valObject;
Py_ssize_t lsize; Py_ssize_t lsize;
dict = dict_alloc(); if (!(dict = dict_alloc()))
if (dict == NULL)
{
PyErr_NoMemory();
return -1; return -1;
}
tv->v_type = VAR_DICT; tv->v_type = VAR_DICT;
tv->vval.v_dict = dict; tv->vval.v_dict = dict;
list = PyMapping_Items(obj); list = PyMapping_Items(obj);
if (list == NULL) if (list == NULL)
{
dict_unref(dict);
return -1; return -1;
}
lsize = PyList_Size(list); lsize = PyList_Size(list);
while (lsize--) while (lsize--)
{ {
@ -4104,6 +4121,7 @@ pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (litem == NULL) if (litem == NULL)
{ {
Py_DECREF(list); Py_DECREF(list);
dict_unref(dict);
return -1; return -1;
} }
@ -4111,15 +4129,25 @@ pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
{ {
Py_DECREF(list); Py_DECREF(list);
Py_DECREF(litem); Py_DECREF(litem);
dict_unref(dict);
return -1; return -1;
} }
DICTKEY_GET(-1, 1) if (!DICTKEY_SET_KEY)
{
dict_unref(dict);
Py_DECREF(list);
Py_DECREF(litem);
DICTKEY_UNREF
return -1;
}
DICTKEY_CHECK_EMPTY(-1)
if (!(valObject = PyTuple_GetItem(litem, 1))) if (!(valObject = PyTuple_GetItem(litem, 1)))
{ {
Py_DECREF(list); Py_DECREF(list);
Py_DECREF(litem); Py_DECREF(litem);
dict_unref(dict);
DICTKEY_UNREF DICTKEY_UNREF
return -1; return -1;
} }
@ -4133,7 +4161,7 @@ pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (di == NULL) if (di == NULL)
{ {
Py_DECREF(list); Py_DECREF(list);
Py_DECREF(valObject); dict_unref(dict);
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
@ -4142,75 +4170,87 @@ pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1) if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
{ {
vim_free(di); vim_free(di);
dict_unref(dict);
Py_DECREF(list); Py_DECREF(list);
Py_DECREF(valObject);
return -1; return -1;
} }
Py_DECREF(valObject);
if (dict_add(dict, di) == FAIL) if (dict_add(dict, di) == FAIL)
{ {
clear_tv(&di->di_tv); dictitem_free(di);
vim_free(di); dict_unref(dict);
Py_DECREF(list); Py_DECREF(list);
PyErr_SetVim(_("failed to add key to dictionary")); PyErr_SetVim(_("failed to add key to dictionary"));
return -1; return -1;
} }
} }
--dict->dv_refcount;
Py_DECREF(list); Py_DECREF(list);
return 0; return 0;
} }
static list_T *
py_list_alloc()
{
list_T *r;
if (!(r = list_alloc()))
{
PyErr_NoMemory();
return NULL;
}
++r->lv_refcount;
return r;
}
static int static int
pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict) pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
{ {
list_T *l; list_T *l;
l = list_alloc(); if (!(l = py_list_alloc()))
if (l == NULL)
{
PyErr_NoMemory();
return -1; return -1;
}
tv->v_type = VAR_LIST; tv->v_type = VAR_LIST;
tv->vval.v_list = l; tv->vval.v_list = l;
if (list_py_concat(l, obj, lookup_dict) == -1) if (list_py_concat(l, obj, lookup_dict) == -1)
{
list_unref(l);
return -1; return -1;
}
--l->lv_refcount;
return 0; return 0;
} }
static int static int
pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict) pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
{ {
PyObject *iterator = PyObject_GetIter(obj); PyObject *iterator;
PyObject *item; PyObject *item;
list_T *l; list_T *l;
listitem_T *li; listitem_T *li;
l = list_alloc(); if (!(l = py_list_alloc()))
if (l == NULL)
{
PyErr_NoMemory();
return -1; return -1;
}
tv->vval.v_list = l; tv->vval.v_list = l;
tv->v_type = VAR_LIST; tv->v_type = VAR_LIST;
if (!(iterator = PyObject_GetIter(obj)))
if (iterator == NULL) {
list_unref(l);
return -1; return -1;
}
while ((item = PyIter_Next(iterator))) while ((item = PyIter_Next(iterator)))
{ {
li = listitem_alloc(); li = listitem_alloc();
if (li == NULL) if (li == NULL)
{ {
list_unref(l);
Py_DECREF(iterator); Py_DECREF(iterator);
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
@ -4219,6 +4259,8 @@ pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1) if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
{ {
list_unref(l);
listitem_free(li);
Py_DECREF(item); Py_DECREF(item);
Py_DECREF(iterator); Py_DECREF(iterator);
return -1; return -1;
@ -4230,6 +4272,15 @@ pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
} }
Py_DECREF(iterator); Py_DECREF(iterator);
/* Iterator may have finished due to an exception */
if (PyErr_Occurred())
{
list_unref(l);
return -1;
}
--l->lv_refcount;
return 0; return 0;
} }
@ -4295,7 +4346,8 @@ ConvertFromPyObject(PyObject *obj, typval_T *tv)
PyObject *lookup_dict; PyObject *lookup_dict;
int r; int r;
lookup_dict = PyDict_New(); if (!(lookup_dict = PyDict_New()))
return -1;
r = _ConvertFromPyObject(obj, tv, lookup_dict); r = _ConvertFromPyObject(obj, tv, lookup_dict);
Py_DECREF(lookup_dict); Py_DECREF(lookup_dict);
return r; return r;

View File

@ -49,6 +49,7 @@ list_T *list_alloc __ARGS((void));
void list_unref __ARGS((list_T *l)); void list_unref __ARGS((list_T *l));
void list_free __ARGS((list_T *l, int recurse)); void list_free __ARGS((list_T *l, int recurse));
listitem_T *listitem_alloc __ARGS((void)); listitem_T *listitem_alloc __ARGS((void));
void listitem_free __ARGS((listitem_T *item));
void listitem_remove __ARGS((list_T *l, listitem_T *item)); void listitem_remove __ARGS((list_T *l, listitem_T *item));
dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
listitem_T *list_find __ARGS((list_T *l, long n)); listitem_T *list_find __ARGS((list_T *l, long n));
@ -65,6 +66,7 @@ void set_ref_in_list __ARGS((list_T *l, int copyID));
void set_ref_in_item __ARGS((typval_T *tv, int copyID)); void set_ref_in_item __ARGS((typval_T *tv, int copyID));
dict_T *dict_alloc __ARGS((void)); dict_T *dict_alloc __ARGS((void));
void dict_unref __ARGS((dict_T *d)); void dict_unref __ARGS((dict_T *d));
void dict_free __ARGS((dict_T *d, int recurse));
dictitem_T *dictitem_alloc __ARGS((char_u *key)); dictitem_T *dictitem_alloc __ARGS((char_u *key));
void dictitem_free __ARGS((dictitem_T *item)); void dictitem_free __ARGS((dictitem_T *item));
int dict_add __ARGS((dict_T *d, dictitem_T *item)); int dict_add __ARGS((dict_T *d, dictitem_T *item));

View File

@ -728,6 +728,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 */
/**/
1056,
/**/ /**/
1055, 1055,
/**/ /**/