Mercurial > vim
diff src/vim9compile.c @ 24363:1a145eb83a28 v8.2.2722
patch 8.2.2722: Vim9: crash when using LHS with double index
Commit: https://github.com/vim/vim/commit/b9c0cd897ab4ad54f514187e89719c0241393f8b
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Apr 5 20:51:00 2021 +0200
patch 8.2.2722: Vim9: crash when using LHS with double index
Problem: Vim9: crash when using LHS with double index.
Solution: Handle lhs_dest which is "dest_expr". (closes https://github.com/vim/vim/issues/8068)
Fix confusing error message for missing dict item.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 05 Apr 2021 21:00:04 +0200 |
parents | f76398d79c2e |
children | f9f8cceaece3 |
line wrap: on
line diff
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6094,6 +6094,48 @@ compile_assign_index( } /* + * For a LHS with an index, load the variable to be indexed. + */ + static int +compile_load_lhs( + lhs_T *lhs, + char_u *var_start, + type_T *rhs_type, + cctx_T *cctx) +{ + if (lhs->lhs_dest == dest_expr) + { + size_t varlen = lhs->lhs_varlen; + int c = var_start[varlen]; + char_u *p = var_start; + garray_T *stack = &cctx->ctx_type_stack; + + // Evaluate "ll[expr]" of "ll[expr][idx]" + var_start[varlen] = NUL; + if (compile_expr0(&p, cctx) == OK && p != var_start + varlen) + { + // this should not happen + emsg(_(e_missbrac)); + return FAIL; + } + var_start[varlen] = c; + + lhs->lhs_type = stack->ga_len == 0 ? &t_void + : ((type_T **)stack->ga_data)[stack->ga_len - 1]; + // now we can properly check the type + if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL + && rhs_type != &t_void + && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, + FALSE, FALSE) == FAIL) + return FAIL; + } + else + generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, + lhs->lhs_lvar, lhs->lhs_type); + return OK; +} + +/* * Assignment to a list or dict member, or ":unlet" for the item, using the * information in "lhs". * Returns OK or FAIL. @@ -6106,9 +6148,7 @@ compile_assign_unlet( type_T *rhs_type, cctx_T *cctx) { - char_u *p; vartype_T dest_type; - size_t varlen = lhs->lhs_varlen; garray_T *stack = &cctx->ctx_type_stack; int range = FALSE; @@ -6147,32 +6187,8 @@ compile_assign_unlet( // - index // - for [a : b] second index // - variable - if (lhs->lhs_dest == dest_expr) - { - int c = var_start[varlen]; - - // Evaluate "ll[expr]" of "ll[expr][idx]" - p = var_start; - var_start[varlen] = NUL; - if (compile_expr0(&p, cctx) == OK && p != var_start + varlen) - { - // this should not happen - emsg(_(e_missbrac)); - return FAIL; - } - var_start[varlen] = c; - - lhs->lhs_type = stack->ga_len == 0 ? &t_void - : ((type_T **)stack->ga_data)[stack->ga_len - 1]; - // now we can properly check the type - if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void - && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, - FALSE, FALSE) == FAIL) - return FAIL; - } - else - generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, - lhs->lhs_lvar, lhs->lhs_type); + if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL) + return FAIL; if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY) { @@ -6384,8 +6400,7 @@ compile_assignment(char_u *arg, exarg_T // for "+=", "*=", "..=" etc. first load the current value if (*op != '=') { - generate_loadvar(cctx, lhs.lhs_dest, lhs.lhs_name, - lhs.lhs_lvar, lhs.lhs_type); + compile_load_lhs(&lhs, var_start, NULL, cctx); if (lhs.lhs_has_index) {