patch 8.2.3029: Vim9: crash when using operator and list unpack assignment
Problem: Vim9: crash when using operator and list unpack assignment.
(Naohiro Ono)
Solution: Get variable value before operation. (closes #8416)
diff --git a/src/vim9compile.c b/src/vim9compile.c
index e4656c9..c5a2c2d 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1240,13 +1240,16 @@
/*
* Generate an ISN_GETITEM instruction with "index".
+ * "with_op" is TRUE for "+=" and other operators, the stack has the current
+ * value below the list with values.
*/
static int
-generate_GETITEM(cctx_T *cctx, int index)
+generate_GETITEM(cctx_T *cctx, int index, int with_op)
{
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
- type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+ type_T *type = ((type_T **)stack->ga_data)[stack->ga_len
+ - (with_op ? 2 : 1)];
type_T *item_type = &t_any;
RETURN_OK_IF_SKIP(cctx);
@@ -1260,7 +1263,8 @@
item_type = type->tt_member;
if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
return FAIL;
- isn->isn_arg.number = index;
+ isn->isn_arg.getitem.gi_index = index;
+ isn->isn_arg.getitem.gi_with_op = with_op;
// add the item type to the type stack
if (ga_grow(stack, 1) == FAIL)
@@ -6746,19 +6750,17 @@
int is_const = FALSE;
char_u *wp;
+ // for "+=", "*=", "..=" etc. first load the current value
+ if (*op != '='
+ && compile_load_lhs_with_index(&lhs, var_start,
+ cctx) == FAIL)
+ goto theend;
+
// For "var = expr" evaluate the expression.
if (var_count == 0)
{
int r;
- // for "+=", "*=", "..=" etc. first load the current value
- if (*op != '=')
- {
- if (compile_load_lhs_with_index(&lhs, var_start,
- cctx) == FAIL)
- goto theend;
- }
-
// Compile the expression.
instr_count = instr->ga_len;
if (incdec)
@@ -6795,7 +6797,7 @@
{
// For "[var, var] = expr" get the "var_idx" item from the
// list.
- if (generate_GETITEM(cctx, var_idx) == FAIL)
+ if (generate_GETITEM(cctx, var_idx, *op != '=') == FAIL)
goto theend;
}