# HG changeset patch
# User ZyX <[email protected]>
# Date 1369520053 -14400
# Node ID 484d93ca3c0244e847c101b6f550f8b8c94ae6f6
# Parent  72a773f3fc682f63c79d1b8481626fdec3198ddd
More possible memory leak fixes and error checking

diff -r 72a773f3fc68 -r 484d93ca3c02 src/eval.c
--- a/src/eval.c        Sat May 25 22:40:17 2013 +0400
+++ b/src/eval.c        Sun May 26 02:14:13 2013 +0400
@@ -412,7 +412,6 @@
 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 rettv_list_alloc __ARGS((typval_T *rettv));
-static void listitem_free __ARGS((listitem_T *item));
 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 dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
@@ -428,7 +427,6 @@
 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 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 void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
 static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
@@ -5955,7 +5953,7 @@
 /*
  * Free a list item.  Also clears the value.  Does not notify watchers.
  */
-    static void
+    void
 listitem_free(item)
     listitem_T *item;
 {
@@ -7031,7 +7029,7 @@
  * Free a Dictionary, including all items it contains.
  * Ignores the reference count.
  */
-    static void
+    void
 dict_free(d, recurse)
     dict_T  *d;
     int            recurse;    /* Free Lists and Dictionaries recursively. */
diff -r 72a773f3fc68 -r 484d93ca3c02 src/if_py_both.h
--- a/src/if_py_both.h  Sat May 25 22:40:17 2013 +0400
+++ b/src/if_py_both.h  Sun May 26 02:14:13 2013 +0400
@@ -32,8 +32,15 @@
 
 #define DICTKEY_DECL \
     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) \
-    if (!(key = StringToChars(keyObject, &dictkey_todecref))) \
+    if (!DICTKEY_SET_KEY) \
     { \
        if (decref) \
        { \
@@ -43,11 +50,7 @@
     } \
     if (decref && !dictkey_todecref) \
        dictkey_todecref = keyObject; \
-    if (*key == NUL) \
-    { \
-       PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
-       return err; \
-    }
+    DICTKEY_CHECK_EMPTY(err)
 #define DICTKEY_UNREF \
     Py_XDECREF(dictkey_todecref);
 
@@ -651,9 +654,13 @@
 
     /* Convert the Vim type into a Python type.  Create a dictionary that's
      * used to check for recursive loops. */
-    lookup_dict = PyDict_New();
-    result = VimToPython(our_tv, 1, lookup_dict);
-    Py_DECREF(lookup_dict);
+    if (!(lookup_dict = PyDict_New()))
+       result = NULL;
+    else
+    {
+       result = VimToPython(our_tv, 1, lookup_dict);
+       Py_DECREF(lookup_dict);
+    }
 
 
     Py_BEGIN_ALLOW_THREADS
@@ -1401,7 +1408,9 @@
        return NULL;
     }
 
-    lookup_dict = PyDict_New();
+    if (!(lookup_dict = PyDict_New()))
+       return NULL;
+
     if (list_py_concat(l, obj, lookup_dict) == -1)
     {
        Py_DECREF(lookup_dict);
@@ -4022,12 +4031,8 @@
     PyObject   *valObject;
     Py_ssize_t iter = 0;
 
-    dict = dict_alloc();
-    if (dict == NULL)
-    {
-       PyErr_NoMemory();
+    if (!(dict = py_dict_alloc()))
        return -1;
-    }
 
     tv->v_type = VAR_DICT;
     tv->vval.v_dict = dict;
@@ -4037,9 +4042,17 @@
        DICTKEY_DECL
 
        if (keyObject == NULL || valObject == NULL)
+       {
+           dict_unref(dict);
            return -1;
-
-       DICTKEY_GET(-1, 0)
+       }
+
+       if (!DICTKEY_SET_KEY)
+       {
+           dict_unref(dict);
+           return -1;
+       }
+       DICTKEY_CHECK_EMPTY(-1)
 
        di = dictitem_alloc(key);
 
@@ -4048,6 +4061,7 @@
        if (di == NULL)
        {
            PyErr_NoMemory();
+           dict_unref(dict);
            return -1;
        }
        di->di_tv.v_lock = 0;
@@ -4055,6 +4069,7 @@
        if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
        {
            vim_free(di);
+           dict_unref(dict);
            return -1;
        }
 
@@ -4062,10 +4077,13 @@
        {
            clear_tv(&di->di_tv);
            vim_free(di);
+           dict_unref(dict);
            PyErr_SetVim(_("failed to add key to dictionary"));
            return -1;
        }
     }
+
+    --dict->dv_refcount;
     return 0;
 }
 
@@ -4081,19 +4099,18 @@
     PyObject   *valObject;
     Py_ssize_t lsize;
 
-    dict = dict_alloc();
-    if (dict == NULL)
+    if (!(dict = py_dict_alloc()))
+       return -1;
+
+    tv->v_type = VAR_DICT;
+    tv->vval.v_dict = dict;
+
+    list = PyMapping_Items(obj);
+    if (list == NULL)
     {
-       PyErr_NoMemory();
+       dict_unref(dict);
        return -1;
     }
-
-    tv->v_type = VAR_DICT;
-    tv->vval.v_dict = dict;
-
-    list = PyMapping_Items(obj);
-    if (list == NULL)
-       return -1;
     lsize = PyList_Size(list);
     while (lsize--)
     {
@@ -4103,6 +4120,7 @@
        if (litem == NULL)
        {
            Py_DECREF(list);
+           dict_unref(dict);
            return -1;
        }
 
@@ -4110,18 +4128,28 @@
        {
            Py_DECREF(list);
            Py_DECREF(litem);
+           dict_unref(dict);
            return -1;
        }
 
-       DICTKEY_GET(-1, 1)
-
-       if (!(valObject = PyTuple_GetItem(litem, 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)))
+       {
+           Py_DECREF(list);
+           Py_DECREF(litem);
+           dict_unref(dict);
+           DICTKEY_UNREF
+           return -1;
+       }
 
        Py_DECREF(litem);
 
@@ -4132,7 +4160,7 @@
        if (di == NULL)
        {
            Py_DECREF(list);
-           Py_DECREF(valObject);
+           dict_unref(dict);
            PyErr_NoMemory();
            return -1;
        }
@@ -4141,75 +4169,87 @@
        if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
        {
            vim_free(di);
+           dict_unref(dict);
            Py_DECREF(list);
-           Py_DECREF(valObject);
            return -1;
        }
 
-       Py_DECREF(valObject);
-
        if (dict_add(dict, di) == FAIL)
        {
-           clear_tv(&di->di_tv);
-           vim_free(di);
+           dictitem_free(di);
+           dict_unref(dict);
            Py_DECREF(list);
            PyErr_SetVim(_("failed to add key to dictionary"));
            return -1;
        }
     }
+    --dict->dv_refcount;
     Py_DECREF(list);
     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
 pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
 {
     list_T     *l;
 
-    l = list_alloc();
-    if (l == NULL)
+    if (!(l = py_list_alloc()))
+       return -1;
+
+    tv->v_type = VAR_LIST;
+    tv->vval.v_list = l;
+
+    if (list_py_concat(l, obj, lookup_dict) == -1)
     {
-       PyErr_NoMemory();
+       list_unref(l);
        return -1;
     }
 
-    tv->v_type = VAR_LIST;
-    tv->vval.v_list = l;
-
-    if (list_py_concat(l, obj, lookup_dict) == -1)
-       return -1;
-
+    --l->lv_refcount;
     return 0;
 }
 
     static int
 pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
 {
-    PyObject   *iterator = PyObject_GetIter(obj);
+    PyObject   *iterator;
     PyObject   *item;
     list_T     *l;
     listitem_T *li;
 
-    l = list_alloc();
-
-    if (l == NULL)
+    if (!(l = py_list_alloc()))
+       return -1;
+
+    tv->vval.v_list = l;
+    tv->v_type = VAR_LIST;
+
+    if (!(iterator = PyObject_GetIter(obj)))
     {
-       PyErr_NoMemory();
+       list_unref(l);
        return -1;
     }
 
-    tv->vval.v_list = l;
-    tv->v_type = VAR_LIST;
-
-
-    if (iterator == NULL)
-       return -1;
-
     while ((item = PyIter_Next(iterator)))
     {
        li = listitem_alloc();
        if (li == NULL)
        {
+           list_unref(l);
            Py_DECREF(iterator);
            PyErr_NoMemory();
            return -1;
@@ -4218,6 +4258,8 @@
 
        if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
        {
+           list_unref(l);
+           listitem_free(li);
            Py_DECREF(item);
            Py_DECREF(iterator);
            return -1;
@@ -4229,6 +4271,15 @@
     }
 
     Py_DECREF(iterator);
+
+    /* Iterator may have finished due to an exception */
+    if (PyErr_Occurred())
+    {
+       list_unref(l);
+       return -1;
+    }
+
+    --l->lv_refcount;
     return 0;
 }
 
@@ -4294,7 +4345,8 @@
     PyObject   *lookup_dict;
     int                r;
 
-    lookup_dict = PyDict_New();
+    if (!(lookup_dict = PyDict_New()))
+       return -1;
     r = _ConvertFromPyObject(obj, tv, lookup_dict);
     Py_DECREF(lookup_dict);
     return r;
diff -r 72a773f3fc68 -r 484d93ca3c02 src/proto/eval.pro
--- a/src/proto/eval.pro        Sat May 25 22:40:17 2013 +0400
+++ b/src/proto/eval.pro        Sun May 26 02:14:13 2013 +0400
@@ -49,6 +49,7 @@
 void list_unref __ARGS((list_T *l));
 void list_free __ARGS((list_T *l, int recurse));
 listitem_T *listitem_alloc __ARGS((void));
+void listitem_free __ARGS((listitem_T *item));
 void listitem_remove __ARGS((list_T *l, listitem_T *item));
 dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
 listitem_T *list_find __ARGS((list_T *l, long n));
@@ -65,6 +66,7 @@
 void set_ref_in_item __ARGS((typval_T *tv, int copyID));
 dict_T *dict_alloc __ARGS((void));
 void dict_unref __ARGS((dict_T *d));
+void dict_free __ARGS((dict_T *d, int recurse));
 dictitem_T *dictitem_alloc __ARGS((char_u *key));
 void dictitem_free __ARGS((dictitem_T *item));
 int dict_add __ARGS((dict_T *d, dictitem_T *item));

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


diff -cr vim.72a773f3fc68/src/eval.c vim.484d93ca3c02/src/eval.c
*** vim.72a773f3fc68/src/eval.c	2013-05-26 12:07:00.682798927 +0400
--- vim.484d93ca3c02/src/eval.c	2013-05-26 12:07:00.704787720 +0400
***************
*** 412,418 ****
  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 rettv_list_alloc __ARGS((typval_T *rettv));
- static void listitem_free __ARGS((listitem_T *item));
  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 dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
--- 412,417 ----
***************
*** 428,434 ****
  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 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 void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
  static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
--- 427,432 ----
***************
*** 5955,5961 ****
  /*
   * Free a list item.  Also clears the value.  Does not notify watchers.
   */
!     static void
  listitem_free(item)
      listitem_T *item;
  {
--- 5953,5959 ----
  /*
   * Free a list item.  Also clears the value.  Does not notify watchers.
   */
!     void
  listitem_free(item)
      listitem_T *item;
  {
***************
*** 7031,7037 ****
   * Free a Dictionary, including all items it contains.
   * Ignores the reference count.
   */
!     static void
  dict_free(d, recurse)
      dict_T  *d;
      int	    recurse;	/* Free Lists and Dictionaries recursively. */
--- 7029,7035 ----
   * Free a Dictionary, including all items it contains.
   * Ignores the reference count.
   */
!     void
  dict_free(d, recurse)
      dict_T  *d;
      int	    recurse;	/* Free Lists and Dictionaries recursively. */
diff -cr vim.72a773f3fc68/src/if_py_both.h vim.484d93ca3c02/src/if_py_both.h
*** vim.72a773f3fc68/src/if_py_both.h	2013-05-26 12:07:00.687796380 +0400
--- vim.484d93ca3c02/src/if_py_both.h	2013-05-26 12:07:00.709785174 +0400
***************
*** 32,39 ****
  
  #define DICTKEY_DECL \
      PyObject	*dictkey_todecref;
  #define DICTKEY_GET(err, decref) \
!     if (!(key = StringToChars(keyObject, &dictkey_todecref))) \
      { \
  	if (decref) \
  	{ \
--- 32,46 ----
  
  #define DICTKEY_DECL \
      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) \
!     if (!DICTKEY_SET_KEY) \
      { \
  	if (decref) \
  	{ \
***************
*** 43,53 ****
      } \
      if (decref && !dictkey_todecref) \
  	dictkey_todecref = keyObject; \
!     if (*key == NUL) \
!     { \
! 	PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
! 	return err; \
!     }
  #define DICTKEY_UNREF \
      Py_XDECREF(dictkey_todecref);
  
--- 50,56 ----
      } \
      if (decref && !dictkey_todecref) \
  	dictkey_todecref = keyObject; \
!     DICTKEY_CHECK_EMPTY(err)
  #define DICTKEY_UNREF \
      Py_XDECREF(dictkey_todecref);
  
***************
*** 651,659 ****
  
      /* Convert the Vim type into a Python type.  Create a dictionary that's
       * used to check for recursive loops. */
!     lookup_dict = PyDict_New();
!     result = VimToPython(our_tv, 1, lookup_dict);
!     Py_DECREF(lookup_dict);
  
  
      Py_BEGIN_ALLOW_THREADS
--- 654,666 ----
  
      /* Convert the Vim type into a Python type.  Create a dictionary that's
       * used to check for recursive loops. */
!     if (!(lookup_dict = PyDict_New()))
! 	result = NULL;
!     else
!     {
! 	result = VimToPython(our_tv, 1, lookup_dict);
! 	Py_DECREF(lookup_dict);
!     }
  
  
      Py_BEGIN_ALLOW_THREADS
***************
*** 1401,1407 ****
  	return NULL;
      }
  
!     lookup_dict = PyDict_New();
      if (list_py_concat(l, obj, lookup_dict) == -1)
      {
  	Py_DECREF(lookup_dict);
--- 1408,1416 ----
  	return NULL;
      }
  
!     if (!(lookup_dict = PyDict_New()))
! 	return NULL;
! 
      if (list_py_concat(l, obj, lookup_dict) == -1)
      {
  	Py_DECREF(lookup_dict);
***************
*** 4022,4033 ****
      PyObject	*valObject;
      Py_ssize_t	iter = 0;
  
!     dict = dict_alloc();
!     if (dict == NULL)
!     {
! 	PyErr_NoMemory();
  	return -1;
-     }
  
      tv->v_type = VAR_DICT;
      tv->vval.v_dict = dict;
--- 4031,4038 ----
      PyObject	*valObject;
      Py_ssize_t	iter = 0;
  
!     if (!(dict = py_dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
      tv->vval.v_dict = dict;
***************
*** 4037,4045 ****
  	DICTKEY_DECL
  
  	if (keyObject == NULL || valObject == NULL)
  	    return -1;
  
! 	DICTKEY_GET(-1, 0)
  
  	di = dictitem_alloc(key);
  
--- 4042,4058 ----
  	DICTKEY_DECL
  
  	if (keyObject == NULL || valObject == NULL)
+ 	{
+ 	    dict_unref(dict);
  	    return -1;
+ 	}
  
! 	if (!DICTKEY_SET_KEY)
! 	{
! 	    dict_unref(dict);
! 	    return -1;
! 	}
! 	DICTKEY_CHECK_EMPTY(-1)
  
  	di = dictitem_alloc(key);
  
***************
*** 4048,4053 ****
--- 4061,4067 ----
  	if (di == NULL)
  	{
  	    PyErr_NoMemory();
+ 	    dict_unref(dict);
  	    return -1;
  	}
  	di->di_tv.v_lock = 0;
***************
*** 4055,4060 ****
--- 4069,4075 ----
  	if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
  	{
  	    vim_free(di);
+ 	    dict_unref(dict);
  	    return -1;
  	}
  
***************
*** 4062,4071 ****
--- 4077,4089 ----
  	{
  	    clear_tv(&di->di_tv);
  	    vim_free(di);
+ 	    dict_unref(dict);
  	    PyErr_SetVim(_("failed to add key to dictionary"));
  	    return -1;
  	}
      }
+ 
+     --dict->dv_refcount;
      return 0;
  }
  
***************
*** 4081,4099 ****
      PyObject	*valObject;
      Py_ssize_t	lsize;
  
!     dict = dict_alloc();
!     if (dict == NULL)
!     {
! 	PyErr_NoMemory();
  	return -1;
-     }
  
      tv->v_type = VAR_DICT;
      tv->vval.v_dict = dict;
  
      list = PyMapping_Items(obj);
      if (list == NULL)
  	return -1;
      lsize = PyList_Size(list);
      while (lsize--)
      {
--- 4099,4116 ----
      PyObject	*valObject;
      Py_ssize_t	lsize;
  
!     if (!(dict = py_dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
      tv->vval.v_dict = dict;
  
      list = PyMapping_Items(obj);
      if (list == NULL)
+     {
+ 	dict_unref(dict);
  	return -1;
+     }
      lsize = PyList_Size(list);
      while (lsize--)
      {
***************
*** 4103,4108 ****
--- 4120,4126 ----
  	if (litem == NULL)
  	{
  	    Py_DECREF(list);
+ 	    dict_unref(dict);
  	    return -1;
  	}
  
***************
*** 4110,4124 ****
  	{
  	    Py_DECREF(list);
  	    Py_DECREF(litem);
  	    return -1;
  	}
  
! 	DICTKEY_GET(-1, 1)
  
  	if (!(valObject = PyTuple_GetItem(litem, 1)))
  	{
  	    Py_DECREF(list);
  	    Py_DECREF(litem);
  	    DICTKEY_UNREF
  	    return -1;
  	}
--- 4128,4152 ----
  	{
  	    Py_DECREF(list);
  	    Py_DECREF(litem);
+ 	    dict_unref(dict);
  	    return -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)))
  	{
  	    Py_DECREF(list);
  	    Py_DECREF(litem);
+ 	    dict_unref(dict);
  	    DICTKEY_UNREF
  	    return -1;
  	}
***************
*** 4132,4138 ****
  	if (di == NULL)
  	{
  	    Py_DECREF(list);
! 	    Py_DECREF(valObject);
  	    PyErr_NoMemory();
  	    return -1;
  	}
--- 4160,4166 ----
  	if (di == NULL)
  	{
  	    Py_DECREF(list);
! 	    dict_unref(dict);
  	    PyErr_NoMemory();
  	    return -1;
  	}
***************
*** 4141,4215 ****
  	if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
  	{
  	    vim_free(di);
  	    Py_DECREF(list);
- 	    Py_DECREF(valObject);
  	    return -1;
  	}
  
- 	Py_DECREF(valObject);
- 
  	if (dict_add(dict, di) == FAIL)
  	{
! 	    clear_tv(&di->di_tv);
! 	    vim_free(di);
  	    Py_DECREF(list);
  	    PyErr_SetVim(_("failed to add key to dictionary"));
  	    return -1;
  	}
      }
      Py_DECREF(list);
      return 0;
  }
  
      static int
  pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
  {
      list_T	*l;
  
!     l = list_alloc();
!     if (l == NULL)
!     {
! 	PyErr_NoMemory();
  	return -1;
-     }
  
      tv->v_type = VAR_LIST;
      tv->vval.v_list = l;
  
      if (list_py_concat(l, obj, lookup_dict) == -1)
  	return -1;
  
      return 0;
  }
  
      static int
  pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
  {
!     PyObject	*iterator = PyObject_GetIter(obj);
      PyObject	*item;
      list_T	*l;
      listitem_T	*li;
  
!     l = list_alloc();
! 
!     if (l == NULL)
!     {
! 	PyErr_NoMemory();
  	return -1;
-     }
  
      tv->vval.v_list = l;
      tv->v_type = VAR_LIST;
  
! 
!     if (iterator == NULL)
  	return -1;
  
      while ((item = PyIter_Next(iterator)))
      {
  	li = listitem_alloc();
  	if (li == NULL)
  	{
  	    Py_DECREF(iterator);
  	    PyErr_NoMemory();
  	    return -1;
--- 4169,4255 ----
  	if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
  	{
  	    vim_free(di);
+ 	    dict_unref(dict);
  	    Py_DECREF(list);
  	    return -1;
  	}
  
  	if (dict_add(dict, di) == FAIL)
  	{
! 	    dictitem_free(di);
! 	    dict_unref(dict);
  	    Py_DECREF(list);
  	    PyErr_SetVim(_("failed to add key to dictionary"));
  	    return -1;
  	}
      }
+     --dict->dv_refcount;
      Py_DECREF(list);
      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
  pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
  {
      list_T	*l;
  
!     if (!(l = py_list_alloc()))
  	return -1;
  
      tv->v_type = VAR_LIST;
      tv->vval.v_list = l;
  
      if (list_py_concat(l, obj, lookup_dict) == -1)
+     {
+ 	list_unref(l);
  	return -1;
+     }
  
+     --l->lv_refcount;
      return 0;
  }
  
      static int
  pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
  {
!     PyObject	*iterator;
      PyObject	*item;
      list_T	*l;
      listitem_T	*li;
  
!     if (!(l = py_list_alloc()))
  	return -1;
  
      tv->vval.v_list = l;
      tv->v_type = VAR_LIST;
  
!     if (!(iterator = PyObject_GetIter(obj)))
!     {
! 	list_unref(l);
  	return -1;
+     }
  
      while ((item = PyIter_Next(iterator)))
      {
  	li = listitem_alloc();
  	if (li == NULL)
  	{
+ 	    list_unref(l);
  	    Py_DECREF(iterator);
  	    PyErr_NoMemory();
  	    return -1;
***************
*** 4218,4223 ****
--- 4258,4265 ----
  
  	if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
  	{
+ 	    list_unref(l);
+ 	    listitem_free(li);
  	    Py_DECREF(item);
  	    Py_DECREF(iterator);
  	    return -1;
***************
*** 4229,4234 ****
--- 4271,4285 ----
      }
  
      Py_DECREF(iterator);
+ 
+     /* Iterator may have finished due to an exception */
+     if (PyErr_Occurred())
+     {
+ 	list_unref(l);
+ 	return -1;
+     }
+ 
+     --l->lv_refcount;
      return 0;
  }
  
***************
*** 4294,4300 ****
      PyObject	*lookup_dict;
      int		r;
  
!     lookup_dict = PyDict_New();
      r = _ConvertFromPyObject(obj, tv, lookup_dict);
      Py_DECREF(lookup_dict);
      return r;
--- 4345,4352 ----
      PyObject	*lookup_dict;
      int		r;
  
!     if (!(lookup_dict = PyDict_New()))
! 	return -1;
      r = _ConvertFromPyObject(obj, tv, lookup_dict);
      Py_DECREF(lookup_dict);
      return r;
diff -cr vim.72a773f3fc68/src/proto/eval.pro vim.484d93ca3c02/src/proto/eval.pro
*** vim.72a773f3fc68/src/proto/eval.pro	2013-05-26 12:07:00.667806567 +0400
--- vim.484d93ca3c02/src/proto/eval.pro	2013-05-26 12:07:00.690794852 +0400
***************
*** 49,54 ****
--- 49,55 ----
  void list_unref __ARGS((list_T *l));
  void list_free __ARGS((list_T *l, int recurse));
  listitem_T *listitem_alloc __ARGS((void));
+ void listitem_free __ARGS((listitem_T *item));
  void listitem_remove __ARGS((list_T *l, listitem_T *item));
  dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
  listitem_T *list_find __ARGS((list_T *l, long n));
***************
*** 65,70 ****
--- 66,72 ----
  void set_ref_in_item __ARGS((typval_T *tv, int copyID));
  dict_T *dict_alloc __ARGS((void));
  void dict_unref __ARGS((dict_T *d));
+ void dict_free __ARGS((dict_T *d, int recurse));
  dictitem_T *dictitem_alloc __ARGS((char_u *key));
  void dictitem_free __ARGS((dictitem_T *item));
  int dict_add __ARGS((dict_T *d, dictitem_T *item));

Raspunde prin e-mail lui