Mercurial > vim
diff src/vim9compile.c @ 23171:bb7531f77529 v8.2.2131
patch 8.2.2131: Vim9: crash when lambda uses same var as assignment
Commit: https://github.com/vim/vim/commit/709664cca0b59b69caa1ed40ebfcf00b2c672693
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Dec 12 14:33:41 2020 +0100
patch 8.2.2131: Vim9: crash when lambda uses same var as assignment
Problem: Vim9: crash when lambda uses same var as assignment.
Solution: Do not let lookup_local change lv_from_outer, make a copy.
(closes #7461)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 12 Dec 2020 14:45:05 +0100 |
parents | 6aa8ddf7a3fa |
children | 4d5d12138b36 |
line wrap: on
line diff
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -148,45 +148,51 @@ struct cctx_S { static void delete_def_function_contents(dfunc_T *dfunc); /* - * Lookup variable "name" in the local scope and return it. - * Return NULL if not found. - */ - static lvar_T * -lookup_local(char_u *name, size_t len, cctx_T *cctx) + * Lookup variable "name" in the local scope and return it in "lvar". + * "lvar->lv_from_outer" is set accordingly. + * If "lvar" is NULL only check if the variable can be found. + * Return FAIL if not found. + */ + static int +lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx) { int idx; - lvar_T *lvar; + lvar_T *lvp; if (len == 0) - return NULL; + return FAIL; // Find local in current function scope. for (idx = 0; idx < cctx->ctx_locals.ga_len; ++idx) { - lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; - if (STRNCMP(name, lvar->lv_name, len) == 0 - && STRLEN(lvar->lv_name) == len) - { - lvar->lv_from_outer = FALSE; - return lvar; + lvp = ((lvar_T *)cctx->ctx_locals.ga_data) + idx; + if (STRNCMP(name, lvp->lv_name, len) == 0 + && STRLEN(lvp->lv_name) == len) + { + if (lvar != NULL) + { + *lvar = *lvp; + lvar->lv_from_outer = FALSE; + } + return OK; } } // Find local in outer function scope. if (cctx->ctx_outer != NULL) { - lvar = lookup_local(name, len, cctx->ctx_outer); - if (lvar != NULL) - { - // TODO: are there situations we should not mark the outer scope as - // used? - cctx->ctx_outer_used = TRUE; - lvar->lv_from_outer = TRUE; - return lvar; - } - } - - return NULL; + if (lookup_local(name, len, lvar, cctx->ctx_outer) == OK) + { + if (lvar != NULL) + { + cctx->ctx_outer_used = TRUE; + lvar->lv_from_outer = TRUE; + } + return OK; + } + } + + return FAIL; } /* @@ -377,7 +383,7 @@ check_defined(char_u *p, size_t len, cct p[len] = NUL; if (script_var_exists(p, len, FALSE, cctx) == OK || (cctx != NULL - && (lookup_local(p, len, cctx) != NULL + && (lookup_local(p, len, NULL, cctx) == OK || arg_exists(p, len, NULL, NULL, NULL, cctx) == OK)) || find_imported(p, len, cctx) != NULL || (ufunc = find_func_even_dead(p, FALSE, cctx)) != NULL) @@ -2555,13 +2561,13 @@ compile_load( } else { - lvar_T *lvar = lookup_local(*arg, len, cctx); - - if (lvar != NULL) + lvar_T lvar; + + if (lookup_local(*arg, len, &lvar, cctx) == OK) { - type = lvar->lv_type; - idx = lvar->lv_idx; - if (lvar->lv_from_outer) + type = lvar.lv_type; + idx = lvar.lv_idx; + if (lvar.lv_from_outer) gen_load_outer = TRUE; else gen_load = TRUE; @@ -2763,7 +2769,7 @@ compile_call( // An argument or local variable can be a function reference, this // overrules a function name. - if (lookup_local(namebuf, varlen, cctx) == NULL + if (lookup_local(namebuf, varlen, NULL, cctx) == FAIL && arg_exists(namebuf, varlen, NULL, NULL, NULL, cctx) != OK) { // If we can find the function by name generate the right call. @@ -5366,6 +5372,7 @@ compile_assignment(char_u *arg, exarg_T assign_dest_T dest = dest_local; int opt_flags = 0; int vimvaridx = -1; + lvar_T local_lvar; lvar_T *lvar = NULL; lvar_T arg_lvar; int has_type = FALSE; @@ -5424,8 +5431,10 @@ compile_assignment(char_u *arg, exarg_T goto theend; } - lvar = lookup_local(var_start, varlen, cctx); - if (lvar == NULL) + + if (lookup_local(var_start, varlen, &local_lvar, cctx) == OK) + lvar = &local_lvar; + else { CLEAR_FIELD(arg_lvar); if (arg_exists(var_start, varlen, @@ -6579,8 +6588,7 @@ compile_for(char_u *arg_start, cctx_T *c } else { - var_lvar = lookup_local(arg, varlen, cctx); - if (var_lvar != NULL) + if (lookup_local(arg, varlen, NULL, cctx) == OK) { semsg(_(e_variable_already_declared), arg); goto failed; @@ -7584,7 +7592,7 @@ compile_def_function(ufunc_T *ufunc, int || *ea.cmd == '$' || *ea.cmd == '@' || ((len) > 2 && ea.cmd[1] == ':') - || lookup_local(ea.cmd, len, &cctx) != NULL + || lookup_local(ea.cmd, len, NULL, &cctx) == OK || arg_exists(ea.cmd, len, NULL, NULL, NULL, &cctx) == OK || script_var_exists(ea.cmd, len, @@ -7637,7 +7645,7 @@ compile_def_function(ufunc_T *ufunc, int } } p = find_ex_command(&ea, NULL, starts_with_colon ? NULL - : (void *(*)(char_u *, size_t, cctx_T *))lookup_local, + : (int (*)(char_u *, size_t, void *, cctx_T *))lookup_local, &cctx); if (p == ea.cmd && ea.cmdidx != CMD_SIZE)