comparison 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
comparison
equal deleted inserted replaced
24362:63a46a4e0d55 24363:1a145eb83a28
6092 } 6092 }
6093 return r; 6093 return r;
6094 } 6094 }
6095 6095
6096 /* 6096 /*
6097 * For a LHS with an index, load the variable to be indexed.
6098 */
6099 static int
6100 compile_load_lhs(
6101 lhs_T *lhs,
6102 char_u *var_start,
6103 type_T *rhs_type,
6104 cctx_T *cctx)
6105 {
6106 if (lhs->lhs_dest == dest_expr)
6107 {
6108 size_t varlen = lhs->lhs_varlen;
6109 int c = var_start[varlen];
6110 char_u *p = var_start;
6111 garray_T *stack = &cctx->ctx_type_stack;
6112
6113 // Evaluate "ll[expr]" of "ll[expr][idx]"
6114 var_start[varlen] = NUL;
6115 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen)
6116 {
6117 // this should not happen
6118 emsg(_(e_missbrac));
6119 return FAIL;
6120 }
6121 var_start[varlen] = c;
6122
6123 lhs->lhs_type = stack->ga_len == 0 ? &t_void
6124 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
6125 // now we can properly check the type
6126 if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL
6127 && rhs_type != &t_void
6128 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
6129 FALSE, FALSE) == FAIL)
6130 return FAIL;
6131 }
6132 else
6133 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
6134 lhs->lhs_lvar, lhs->lhs_type);
6135 return OK;
6136 }
6137
6138 /*
6097 * Assignment to a list or dict member, or ":unlet" for the item, using the 6139 * Assignment to a list or dict member, or ":unlet" for the item, using the
6098 * information in "lhs". 6140 * information in "lhs".
6099 * Returns OK or FAIL. 6141 * Returns OK or FAIL.
6100 */ 6142 */
6101 static int 6143 static int
6104 lhs_T *lhs, 6146 lhs_T *lhs,
6105 int is_assign, 6147 int is_assign,
6106 type_T *rhs_type, 6148 type_T *rhs_type,
6107 cctx_T *cctx) 6149 cctx_T *cctx)
6108 { 6150 {
6109 char_u *p;
6110 vartype_T dest_type; 6151 vartype_T dest_type;
6111 size_t varlen = lhs->lhs_varlen;
6112 garray_T *stack = &cctx->ctx_type_stack; 6152 garray_T *stack = &cctx->ctx_type_stack;
6113 int range = FALSE; 6153 int range = FALSE;
6114 6154
6115 if (compile_assign_index(var_start, lhs, is_assign, &range, cctx) == FAIL) 6155 if (compile_assign_index(var_start, lhs, is_assign, &range, cctx) == FAIL)
6116 return FAIL; 6156 return FAIL;
6145 // Load the dict or list. On the stack we then have: 6185 // Load the dict or list. On the stack we then have:
6146 // - value (for assignment, not for :unlet) 6186 // - value (for assignment, not for :unlet)
6147 // - index 6187 // - index
6148 // - for [a : b] second index 6188 // - for [a : b] second index
6149 // - variable 6189 // - variable
6150 if (lhs->lhs_dest == dest_expr) 6190 if (compile_load_lhs(lhs, var_start, rhs_type, cctx) == FAIL)
6151 { 6191 return FAIL;
6152 int c = var_start[varlen];
6153
6154 // Evaluate "ll[expr]" of "ll[expr][idx]"
6155 p = var_start;
6156 var_start[varlen] = NUL;
6157 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen)
6158 {
6159 // this should not happen
6160 emsg(_(e_missbrac));
6161 return FAIL;
6162 }
6163 var_start[varlen] = c;
6164
6165 lhs->lhs_type = stack->ga_len == 0 ? &t_void
6166 : ((type_T **)stack->ga_data)[stack->ga_len - 1];
6167 // now we can properly check the type
6168 if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void
6169 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx,
6170 FALSE, FALSE) == FAIL)
6171 return FAIL;
6172 }
6173 else
6174 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
6175 lhs->lhs_lvar, lhs->lhs_type);
6176 6192
6177 if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY) 6193 if (dest_type == VAR_LIST || dest_type == VAR_DICT || dest_type == VAR_ANY)
6178 { 6194 {
6179 if (is_assign) 6195 if (is_assign)
6180 { 6196 {
6382 int r; 6398 int r;
6383 6399
6384 // for "+=", "*=", "..=" etc. first load the current value 6400 // for "+=", "*=", "..=" etc. first load the current value
6385 if (*op != '=') 6401 if (*op != '=')
6386 { 6402 {
6387 generate_loadvar(cctx, lhs.lhs_dest, lhs.lhs_name, 6403 compile_load_lhs(&lhs, var_start, NULL, cctx);
6388 lhs.lhs_lvar, lhs.lhs_type);
6389 6404
6390 if (lhs.lhs_has_index) 6405 if (lhs.lhs_has_index)
6391 { 6406 {
6392 int range = FALSE; 6407 int range = FALSE;
6393 6408