Patch 7.4.1639
Problem:    Invoking garbage collection may cause a double free.
Solution:   Don't free the dict in a partial when recursive is FALSE.
Files:      src/eval.c


*** ../vim-7.4.1638/src/eval.c  2016-03-22 21:00:06.052953785 +0100
--- src/eval.c  2016-03-22 22:22:09.045823705 +0100
***************
*** 209,215 ****
  /* The names of packages that once were loaded are remembered. */
  static garray_T               ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
  
! /* list heads for garbage collection */
  static dict_T         *first_dict = NULL;     /* list of all dicts */
  static list_T         *first_list = NULL;     /* list of all lists */
  
--- 209,217 ----
  /* The names of packages that once were loaded are remembered. */
  static garray_T               ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
  
! /* List heads for garbage collection. Although there can be a reference loop
!  * from partial to dict to partial, we don't need to keep track of the 
partial,
!  * since it will get freed when the dict is unused and gets freed. */
  static dict_T         *first_dict = NULL;     /* list of all dicts */
  static list_T         *first_list = NULL;     /* list of all lists */
  
***************
*** 7130,7138 ****
      list_T    *ll;
      int               abort = FALSE;
  
!     if (tv->v_type == VAR_DICT)
      {
!       dd = tv->vval.v_dict;
        if (dd != NULL && dd->dv_copyID != copyID)
        {
            /* Didn't see this dict yet. */
--- 7132,7145 ----
      list_T    *ll;
      int               abort = FALSE;
  
!     if (tv->v_type == VAR_DICT || tv->v_type == VAR_PARTIAL)
      {
!       if (tv->v_type == VAR_DICT)
!           dd = tv->vval.v_dict;
!       else if (tv->vval.v_partial != NULL)
!           dd = tv->vval.v_partial->pt_dict;
!       else
!           dd = NULL;
        if (dd != NULL && dd->dv_copyID != copyID)
        {
            /* Didn't see this dict yet. */
***************
*** 7184,7189 ****
--- 7191,7222 ----
      return abort;
  }
  
+     static void
+ partial_free(partial_T *pt, int free_dict)
+ {
+     int i;
+ 
+     for (i = 0; i < pt->pt_argc; ++i)
+       clear_tv(&pt->pt_argv[i]);
+     vim_free(pt->pt_argv);
+     if (free_dict)
+       dict_unref(pt->pt_dict);
+     func_unref(pt->pt_name);
+     vim_free(pt->pt_name);
+     vim_free(pt);
+ }
+ 
+ /*
+  * Unreference a closure: decrement the reference count and free it when it
+  * becomes zero.
+  */
+     void
+ partial_unref(partial_T *pt)
+ {
+     if (pt != NULL && --pt->pt_refcount <= 0)
+       partial_free(pt, TRUE);
+ }
+ 
  /*
   * Allocate an empty header for a dictionary.
   */
***************
*** 7275,7281 ****
            hash_remove(&d->dv_hashtab, hi);
            if (recurse || (di->di_tv.v_type != VAR_LIST
                                             && di->di_tv.v_type != VAR_DICT))
!               clear_tv(&di->di_tv);
            vim_free(di);
            --todo;
        }
--- 7308,7325 ----
            hash_remove(&d->dv_hashtab, hi);
            if (recurse || (di->di_tv.v_type != VAR_LIST
                                             && di->di_tv.v_type != VAR_DICT))
!           {
!               if (!recurse && di->di_tv.v_type == VAR_PARTIAL)
!               {
!                   partial_T *pt = di->di_tv.vval.v_partial;
! 
!                   /* We unref the partial but not the dict it refers to. */
!                   if (pt != NULL && --pt->pt_refcount == 0)
!                       partial_free(pt, FALSE);
!               }
!               else
!                   clear_tv(&di->di_tv);
!           }
            vim_free(di);
            --todo;
        }
***************
*** 12011,12041 ****
      }
  }
  
-     static void
- partial_free(partial_T *pt)
- {
-     int i;
- 
-     for (i = 0; i < pt->pt_argc; ++i)
-       clear_tv(&pt->pt_argv[i]);
-     vim_free(pt->pt_argv);
-     dict_unref(pt->pt_dict);
-     func_unref(pt->pt_name);
-     vim_free(pt->pt_name);
-     vim_free(pt);
- }
- 
- /*
-  * Unreference a closure: decrement the reference count and free it when it
-  * becomes zero.
-  */
-     void
- partial_unref(partial_T *pt)
- {
-     if (pt != NULL && --pt->pt_refcount <= 0)
-       partial_free(pt);
- }
- 
  /*
   * "garbagecollect()" function
   */
--- 12055,12060 ----
*** ../vim-7.4.1638/src/version.c       2016-03-22 21:00:06.052953785 +0100
--- src/version.c       2016-03-22 22:32:46.835179866 +0100
***************
*** 750,751 ****
--- 750,753 ----
  {   /* Add new patch number below this line */
+ /**/
+     1639,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
99. The hum of a cooling fan and the click of keys is comforting to you.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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/d/optout.

Raspunde prin e-mail lui