Mercurial > vim
comparison src/evalvars.c @ 25286:946ef64ede70 v8.2.3180
patch 8.2.3180: Vim9: memory leak when concatenating to an imported string
Commit: https://github.com/vim/vim/commit/f6488547e3c7e41ff2c12dd0b93c9ef04e4c8c6f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jul 18 21:24:50 2021 +0200
patch 8.2.3180: Vim9: memory leak when concatenating to an imported string
Problem: Vim9: memory leak when concatenating to an imported string.
Solution: Clear the destination.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 18 Jul 2021 21:30:03 +0200 |
parents | 29191571eceb |
children | 90fa50a31994 |
comparison
equal
deleted
inserted
replaced
25285:e1da7f3315fa | 25286:946ef64ede70 |
---|---|
3260 sv = ((svar_T *)si->sn_var_vals.ga_data) | 3260 sv = ((svar_T *)si->sn_var_vals.ga_data) |
3261 + import->imp_var_vals_idx; | 3261 + import->imp_var_vals_idx; |
3262 // TODO: check the type | 3262 // TODO: check the type |
3263 // TODO: check for const and locked | 3263 // TODO: check for const and locked |
3264 dest_tv = sv->sv_tv; | 3264 dest_tv = sv->sv_tv; |
3265 clear_tv(dest_tv); | |
3265 } | 3266 } |
3266 } | 3267 } |
3267 | 3268 |
3268 if (dest_tv == NULL) | 3269 if (dest_tv == NULL) |
3269 { | 3270 { |
3270 // Search in parent scope which is possible to reference from lambda | 3271 // Search in parent scope which is possible to reference from lambda |
3271 if (di == NULL) | 3272 if (di == NULL) |
3272 di = find_var_in_scoped_ht(name, TRUE); | 3273 di = find_var_in_scoped_ht(name, TRUE); |
3273 | 3274 |
3274 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) | 3275 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) |
3275 && var_wrong_func_name(name, di == NULL)) | 3276 && var_wrong_func_name(name, di == NULL)) |
3276 goto failed; | 3277 goto failed; |
3277 | 3278 |
3278 if (need_convert_to_bool(type, tv)) | 3279 if (need_convert_to_bool(type, tv)) |
3279 { | 3280 { |
3280 // Destination is a bool and the value is not, but it can be converted. | 3281 // Destination is a bool and the value is not, but it can be |
3282 // converted. | |
3281 CLEAR_FIELD(bool_tv); | 3283 CLEAR_FIELD(bool_tv); |
3282 bool_tv.v_type = VAR_BOOL; | 3284 bool_tv.v_type = VAR_BOOL; |
3283 bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE; | 3285 bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE; |
3284 tv = &bool_tv; | 3286 tv = &bool_tv; |
3285 } | 3287 } |
3288 { | 3290 { |
3289 // Item already exists. Allowed to replace when reloading. | 3291 // Item already exists. Allowed to replace when reloading. |
3290 if ((di->di_flags & DI_FLAGS_RELOAD) == 0) | 3292 if ((di->di_flags & DI_FLAGS_RELOAD) == 0) |
3291 { | 3293 { |
3292 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) | 3294 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) |
3293 && (flags & ASSIGN_FOR_LOOP) == 0) | 3295 && (flags & ASSIGN_FOR_LOOP) == 0) |
3294 { | 3296 { |
3295 emsg(_(e_cannot_mod)); | 3297 emsg(_(e_cannot_mod)); |
3296 goto failed; | 3298 goto failed; |
3297 } | 3299 } |
3298 | 3300 |
3299 if (is_script_local && vim9script | 3301 if (is_script_local && vim9script |
3300 && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0) | 3302 && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0) |
3301 { | 3303 { |
3302 semsg(_(e_redefining_script_item_str), name); | 3304 semsg(_(e_redefining_script_item_str), name); |
3303 goto failed; | 3305 goto failed; |
3304 } | 3306 } |
3305 | 3307 |
3308 where_T where; | 3310 where_T where; |
3309 | 3311 |
3310 // check the type and adjust to bool if needed | 3312 // check the type and adjust to bool if needed |
3311 where.wt_index = var_idx; | 3313 where.wt_index = var_idx; |
3312 where.wt_variable = TRUE; | 3314 where.wt_variable = TRUE; |
3313 if (check_script_var_type(&di->di_tv, tv, name, where) == FAIL) | 3315 if (check_script_var_type(&di->di_tv, tv, name, where) |
3316 == FAIL) | |
3314 goto failed; | 3317 goto failed; |
3315 } | 3318 } |
3316 | 3319 |
3317 if (var_check_permission(di, name) == FAIL) | 3320 if (var_check_permission(di, name) == FAIL) |
3318 goto failed; | 3321 goto failed; |
3320 else | 3323 else |
3321 { | 3324 { |
3322 // can only redefine once | 3325 // can only redefine once |
3323 di->di_flags &= ~DI_FLAGS_RELOAD; | 3326 di->di_flags &= ~DI_FLAGS_RELOAD; |
3324 | 3327 |
3325 // A Vim9 script-local variable is also present in sn_all_vars and | 3328 // A Vim9 script-local variable is also present in sn_all_vars |
3326 // sn_var_vals. It may set "type" from "tv". | 3329 // and sn_var_vals. It may set "type" from "tv". |
3327 if (var_in_vim9script) | 3330 if (var_in_vim9script) |
3328 update_vim9_script_var(FALSE, di, flags, tv, &type, | 3331 update_vim9_script_var(FALSE, di, flags, tv, &type, |
3329 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); | 3332 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); |
3330 } | 3333 } |
3331 | 3334 |
3332 // existing variable, need to clear the value | 3335 // existing variable, need to clear the value |
3333 | 3336 |
3334 // Handle setting internal di: variables separately where needed to | 3337 // Handle setting internal di: variables separately where needed to |
3340 VIM_CLEAR(di->di_tv.vval.v_string); | 3343 VIM_CLEAR(di->di_tv.vval.v_string); |
3341 if (copy || tv->v_type != VAR_STRING) | 3344 if (copy || tv->v_type != VAR_STRING) |
3342 { | 3345 { |
3343 char_u *val = tv_get_string(tv); | 3346 char_u *val = tv_get_string(tv); |
3344 | 3347 |
3345 // Careful: when assigning to v:errmsg and tv_get_string() | 3348 // Careful: when assigning to v:errmsg and |
3346 // causes an error message the variable will already be set. | 3349 // tv_get_string() causes an error message the variable |
3350 // will already be set. | |
3347 if (di->di_tv.vval.v_string == NULL) | 3351 if (di->di_tv.vval.v_string == NULL) |
3348 di->di_tv.vval.v_string = vim_strsave(val); | 3352 di->di_tv.vval.v_string = vim_strsave(val); |
3349 } | 3353 } |
3350 else | 3354 else |
3351 { | 3355 { |
3357 } | 3361 } |
3358 else if (di->di_tv.v_type == VAR_NUMBER) | 3362 else if (di->di_tv.v_type == VAR_NUMBER) |
3359 { | 3363 { |
3360 di->di_tv.vval.v_number = tv_get_number(tv); | 3364 di->di_tv.vval.v_number = tv_get_number(tv); |
3361 if (STRCMP(varname, "searchforward") == 0) | 3365 if (STRCMP(varname, "searchforward") == 0) |
3362 set_search_direction(di->di_tv.vval.v_number ? '/' : '?'); | 3366 set_search_direction(di->di_tv.vval.v_number |
3367 ? '/' : '?'); | |
3363 #ifdef FEAT_SEARCH_EXTRA | 3368 #ifdef FEAT_SEARCH_EXTRA |
3364 else if (STRCMP(varname, "hlsearch") == 0) | 3369 else if (STRCMP(varname, "hlsearch") == 0) |
3365 { | 3370 { |
3366 no_hlsearch = !di->di_tv.vval.v_number; | 3371 no_hlsearch = !di->di_tv.vval.v_number; |
3367 redraw_all_later(SOME_VALID); | 3372 redraw_all_later(SOME_VALID); |
3380 } | 3385 } |
3381 else | 3386 else |
3382 { | 3387 { |
3383 // Item not found, check if a function already exists. | 3388 // Item not found, check if a function already exists. |
3384 if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0 | 3389 if (is_script_local && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0 |
3385 && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK) | 3390 && lookup_scriptitem(name, STRLEN(name), FALSE, NULL) == OK) |
3386 { | 3391 { |
3387 semsg(_(e_redefining_script_item_str), name); | 3392 semsg(_(e_redefining_script_item_str), name); |
3388 goto failed; | 3393 goto failed; |
3389 } | 3394 } |
3390 | 3395 |
3403 } | 3408 } |
3404 | 3409 |
3405 // Make sure the variable name is valid. In Vim9 script an autoload | 3410 // Make sure the variable name is valid. In Vim9 script an autoload |
3406 // variable must be prefixed with "g:". | 3411 // variable must be prefixed with "g:". |
3407 if (!valid_varname(varname, !vim9script | 3412 if (!valid_varname(varname, !vim9script |
3408 || STRNCMP(name, "g:", 2) == 0)) | 3413 || STRNCMP(name, "g:", 2) == 0)) |
3409 goto failed; | 3414 goto failed; |
3410 | 3415 |
3411 di = alloc(sizeof(dictitem_T) + STRLEN(varname)); | 3416 di = alloc(sizeof(dictitem_T) + STRLEN(varname)); |
3412 if (di == NULL) | 3417 if (di == NULL) |
3413 goto failed; | 3418 goto failed; |
3423 | 3428 |
3424 // A Vim9 script-local variable is also added to sn_all_vars and | 3429 // A Vim9 script-local variable is also added to sn_all_vars and |
3425 // sn_var_vals. It may set "type" from "tv". | 3430 // sn_var_vals. It may set "type" from "tv". |
3426 if (var_in_vim9script) | 3431 if (var_in_vim9script) |
3427 update_vim9_script_var(TRUE, di, flags, tv, &type, | 3432 update_vim9_script_var(TRUE, di, flags, tv, &type, |
3428 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); | 3433 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); |
3429 } | 3434 } |
3430 | 3435 |
3431 dest_tv = &di->di_tv; | 3436 dest_tv = &di->di_tv; |
3432 } | 3437 } |
3433 | 3438 |