Patch 8.2.3771
Problem:    Vim9: accessing freed memory when checking type.
Solution:   Make a copy of a function type.
Files:      src/structs.h, src/evalvars.c, src/vim9script.c,
            src/testdir/test_vim9_func.vim


*** ../vim-8.2.3770/src/structs.h       2021-12-03 11:08:34.260842706 +0000
--- src/structs.h       2021-12-10 10:03:56.622486762 +0000
***************
*** 1809,1814 ****
--- 1809,1815 ----
      char_u    *sv_name;       // points into "sn_all_vars" di_key
      typval_T  *sv_tv;         // points into "sn_vars" or "sn_all_vars" di_tv
      type_T    *sv_type;
+     int               sv_type_allocated;  // call free_type() for sv_type
      int               sv_const;       // 0, ASSIGN_CONST or ASSIGN_FINAL
      int               sv_export;      // "export let var = val"
  };
*** ../vim-8.2.3770/src/evalvars.c      2021-12-07 11:03:35.260224997 +0000
--- src/evalvars.c      2021-12-10 10:37:20.167846971 +0000
***************
*** 3291,3296 ****
--- 3291,3297 ----
      int               vim9script = in_vim9script();
      int               var_in_vim9script;
      int               flags = flags_arg;
+     int               free_tv_arg = !copy;  // free tv_arg if not used
  
      ht = find_var_ht(name, &varname);
      if (ht == NULL || *varname == NUL)
***************
*** 3545,3550 ****
--- 3546,3552 ----
        dest_tv->v_lock = 0;
        init_tv(tv);
      }
+     free_tv_arg = FALSE;
  
      if (vim9script && type != NULL)
      {
***************
*** 3573,3582 ****
        // if the reference count is up to one.  That locks only literal
        // values.
        item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
-     return;
  
  failed:
!     if (!copy)
        clear_tv(tv_arg);
  }
  
--- 3575,3583 ----
        // if the reference count is up to one.  That locks only literal
        // values.
        item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);
  
  failed:
!     if (free_tv_arg)
        clear_tv(tv_arg);
  }
  
*** ../vim-8.2.3770/src/vim9script.c    2021-11-26 17:36:48.008799188 +0000
--- src/vim9script.c    2021-12-10 10:15:37.557204820 +0000
***************
*** 268,273 ****
--- 268,274 ----
      hashitem_T        *hi;
      sallvar_T *sav;
      sallvar_T *sav_next;
+     int               idx;
  
      hash_lock(ht);
      todo = (int)ht->ht_used;
***************
*** 293,298 ****
--- 294,306 ----
      hash_clear(ht);
      hash_init(ht);
  
+     for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx)
+     {
+       svar_T    *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
+ 
+       if (sv->sv_type_allocated)
+           free_type(sv->sv_type);
+     }
      ga_clear(&si->sn_var_vals);
  
      // existing commands using script variable indexes are no longer valid
***************
*** 899,905 ****
      {
        if (*type == NULL)
            *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member);
!       sv->sv_type = *type;
      }
  
      // let ex_export() know the export worked.
--- 907,928 ----
      {
        if (*type == NULL)
            *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member);
!       if (sv->sv_type_allocated)
!           free_type(sv->sv_type);
!       if (*type != NULL && ((*type)->tt_type == VAR_FUNC
!                                          || (*type)->tt_type == VAR_PARTIAL))
!       {
!           // The type probably uses uf_type_list, which is cleared when the
!           // function is freed, but the script variable may keep the type.
!           // Make a copy to avoid using freed memory.
!           sv->sv_type = alloc_type(*type);
!           sv->sv_type_allocated = TRUE;
!       }
!       else
!       {
!           sv->sv_type = *type;
!           sv->sv_type_allocated = FALSE;
!       }
      }
  
      // let ex_export() know the export worked.
*** ../vim-8.2.3770/src/testdir/test_vim9_func.vim      2021-12-09 
14:23:40.261634977 +0000
--- src/testdir/test_vim9_func.vim      2021-12-10 10:32:22.144283133 +0000
***************
*** 1224,1229 ****
--- 1224,1248 ----
    CheckScriptSuccess(lines)
  enddef
  
+ def Test_lambda_type_allocated()
+   # Check that unreferencing a partial using a lambda can use the variable 
type
+   # after the lambda has been freed and does not leak memory.
+   var lines =<< trim END
+     vim9script
+ 
+     func MyomniFunc1(val, findstart, base)
+       return a:findstart ? 0 : []
+     endfunc
+ 
+     var Lambda = (a, b) => MyomniFunc1(19, a, b)
+     &omnifunc = Lambda
+     Lambda = (a, b) => MyomniFunc1(20, a, b)
+     &omnifunc = string(Lambda)
+     Lambda = (a, b) => strlen(a)
+   END
+   CheckScriptSuccess(lines)
+ enddef
+ 
  " Default arg and varargs
  def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
    var res = one .. ',' .. two
*** ../vim-8.2.3770/src/version.c       2021-12-09 21:07:07.604331912 +0000
--- src/version.c       2021-12-10 10:16:28.873200936 +0000
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     3771,
  /**/

-- 
Q: What is the difference between open-source and commercial software?
A: If you have a problem with commercial software you can call a phone
   number and they will tell you it might be solved in a future version.
   For open-source software there isn't a phone number to call, but you
   get the solution within a day.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20211210103809.8A2EE1C09BB%40moolenaar.net.

Raspunde prin e-mail lui