Mercurial > vim
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 |