Patch 8.2.3180
Problem:    Vim9: memory leak when concatenating to an imported string.
Solution:   Clear the destination.
Files:      src/evalvars.c


*** ../vim-8.2.3179/src/evalvars.c      2021-07-18 20:40:29.550272444 +0200
--- src/evalvars.c      2021-07-18 21:16:48.183374985 +0200
***************
*** 3262,3267 ****
--- 3262,3268 ----
            // TODO: check the type
            // TODO: check for const and locked
            dest_tv = sv->sv_tv;
+           clear_tv(dest_tv);
        }
      }
  
***************
*** 3272,3283 ****
            di = find_var_in_scoped_ht(name, TRUE);
  
        if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
!                                         && var_wrong_func_name(name, di == 
NULL))
            goto failed;
  
        if (need_convert_to_bool(type, tv))
        {
!           // Destination is a bool and the value is not, but it can be 
converted.
            CLEAR_FIELD(bool_tv);
            bool_tv.v_type = VAR_BOOL;
            bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
--- 3273,3285 ----
            di = find_var_in_scoped_ht(name, TRUE);
  
        if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
!                                     && var_wrong_func_name(name, di == NULL))
            goto failed;
  
        if (need_convert_to_bool(type, tv))
        {
!           // Destination is a bool and the value is not, but it can be
!           // converted.
            CLEAR_FIELD(bool_tv);
            bool_tv.v_type = VAR_BOOL;
            bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
***************
*** 3290,3303 ****
            if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
            {
                if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
!                                                && (flags & ASSIGN_FOR_LOOP) 
== 0)
                {
                    emsg(_(e_cannot_mod));
                    goto failed;
                }
  
                if (is_script_local && vim9script
!                                 && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) 
== 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
                    goto failed;
--- 3292,3305 ----
            if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
            {
                if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
!                                            && (flags & ASSIGN_FOR_LOOP) == 0)
                {
                    emsg(_(e_cannot_mod));
                    goto failed;
                }
  
                if (is_script_local && vim9script
!                             && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
                {
                    semsg(_(e_redefining_script_item_str), name);
                    goto failed;
***************
*** 3310,3316 ****
                    // check the type and adjust to bool if needed
                    where.wt_index = var_idx;
                    where.wt_variable = TRUE;
!                   if (check_script_var_type(&di->di_tv, tv, name, where) == 
FAIL)
                        goto failed;
                }
  
--- 3312,3319 ----
                    // check the type and adjust to bool if needed
                    where.wt_index = var_idx;
                    where.wt_variable = TRUE;
!                   if (check_script_var_type(&di->di_tv, tv, name, where)
!                                                                      == FAIL)
                        goto failed;
                }
  
***************
*** 3322,3332 ****
                // can only redefine once
                di->di_flags &= ~DI_FLAGS_RELOAD;
  
!               // A Vim9 script-local variable is also present in sn_all_vars 
and
!               // sn_var_vals.  It may set "type" from "tv".
                if (var_in_vim9script)
                    update_vim9_script_var(FALSE, di, flags, tv, &type,
!                                            (flags & ASSIGN_NO_MEMBER_TYPE) == 
0);
            }
  
            // existing variable, need to clear the value
--- 3325,3335 ----
                // can only redefine once
                di->di_flags &= ~DI_FLAGS_RELOAD;
  
!               // A Vim9 script-local variable is also present in sn_all_vars
!               // and sn_var_vals.  It may set "type" from "tv".
                if (var_in_vim9script)
                    update_vim9_script_var(FALSE, di, flags, tv, &type,
!                                        (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
            }
  
            // existing variable, need to clear the value
***************
*** 3342,3349 ****
                    {
                        char_u *val = tv_get_string(tv);
  
!                       // Careful: when assigning to v:errmsg and 
tv_get_string()
!                       // causes an error message the variable will already be 
set.
                        if (di->di_tv.vval.v_string == NULL)
                            di->di_tv.vval.v_string = vim_strsave(val);
                    }
--- 3345,3353 ----
                    {
                        char_u *val = tv_get_string(tv);
  
!                       // Careful: when assigning to v:errmsg and
!                       // tv_get_string() causes an error message the variable
!                       // will already be set.
                        if (di->di_tv.vval.v_string == NULL)
                            di->di_tv.vval.v_string = vim_strsave(val);
                    }
***************
*** 3359,3365 ****
                {
                    di->di_tv.vval.v_number = tv_get_number(tv);
                    if (STRCMP(varname, "searchforward") == 0)
!                       set_search_direction(di->di_tv.vval.v_number ? '/' : 
'?');
  #ifdef FEAT_SEARCH_EXTRA
                    else if (STRCMP(varname, "hlsearch") == 0)
                    {
--- 3363,3370 ----
                {
                    di->di_tv.vval.v_number = tv_get_number(tv);
                    if (STRCMP(varname, "searchforward") == 0)
!                       set_search_direction(di->di_tv.vval.v_number
!                                                                 ? '/' : '?');
  #ifdef FEAT_SEARCH_EXTRA
                    else if (STRCMP(varname, "hlsearch") == 0)
                    {
***************
*** 3382,3388 ****
        {
            // Item not found, check if a function already exists.
            if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
!                      && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == 
OK)
            {
                semsg(_(e_redefining_script_item_str), name);
                goto failed;
--- 3387,3393 ----
        {
            // Item not found, check if a function already exists.
            if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
!                  && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK)
            {
                semsg(_(e_redefining_script_item_str), name);
                goto failed;
***************
*** 3405,3411 ****
            // Make sure the variable name is valid.  In Vim9 script an autoload
            // variable must be prefixed with "g:".
            if (!valid_varname(varname, !vim9script
!                                                  || STRNCMP(name, "g:", 2) == 
0))
                goto failed;
  
            di = alloc(sizeof(dictitem_T) + STRLEN(varname));
--- 3410,3416 ----
            // Make sure the variable name is valid.  In Vim9 script an autoload
            // variable must be prefixed with "g:".
            if (!valid_varname(varname, !vim9script
!                                              || STRNCMP(name, "g:", 2) == 0))
                goto failed;
  
            di = alloc(sizeof(dictitem_T) + STRLEN(varname));
***************
*** 3425,3431 ****
            // sn_var_vals. It may set "type" from "tv".
            if (var_in_vim9script)
                update_vim9_script_var(TRUE, di, flags, tv, &type,
!                                            (flags & ASSIGN_NO_MEMBER_TYPE) == 
0);
        }
  
        dest_tv = &di->di_tv;
--- 3430,3436 ----
            // sn_var_vals. It may set "type" from "tv".
            if (var_in_vim9script)
                update_vim9_script_var(TRUE, di, flags, tv, &type,
!                                        (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
        }
  
        dest_tv = &di->di_tv;
*** ../vim-8.2.3179/src/version.c       2021-07-18 20:40:29.550272444 +0200
--- src/version.c       2021-07-18 21:18:16.255243684 +0200
***************
*** 757,758 ****
--- 757,760 ----
  {   /* Add new patch number below this line */
+ /**/
+     3180,
  /**/

-- 
If Microsoft would build a car...
... The airbag system would ask "are you SURE?" before deploying.

 /// 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/202107181925.16IJPH5w2824361%40masaka.moolenaar.net.

Raspunde prin e-mail lui