diff options
author | Bram Moolenaar <Bram@vim.org> | 2023-02-18 18:38:37 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2023-02-18 18:38:37 +0000 |
commit | 2c1c803c7e0cc356dd55a2cd49fbffbbf7db766e (patch) | |
tree | a9b33c47978efd0ffaf3f1ef10e547edc15d5b3e /src/vim9execute.c | |
parent | d114975b9bec30ec1486ebc70db6b802d0f1cfb8 (diff) |
patch 9.0.1322: crash when indexing "any" which is an objectv9.0.1322
Problem: Crash when indexing "any" which is an object.
Solution: Check the index is a number. Do not check the member type of an
object. (closes #12019)
Diffstat (limited to 'src/vim9execute.c')
-rw-r--r-- | src/vim9execute.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/vim9execute.c b/src/vim9execute.c index 4bbed82594..638dbc5ca4 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2126,9 +2126,13 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) vartype_T dest_type = iptr->isn_arg.storeindex.si_vartype; typval_T *tv; typval_T *tv_idx = STACK_TV_BOT(-2); + long lidx = 0; typval_T *tv_dest = STACK_TV_BOT(-1); int status = OK; + if (tv_idx->v_type == VAR_NUMBER) + lidx = (long)tv_idx->vval.v_number; + // Stack contains: // -3 value to be stored // -2 index @@ -2140,7 +2144,41 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) dest_type = tv_dest->v_type; if (dest_type == VAR_DICT) status = do_2string(tv_idx, TRUE, FALSE); - else if (dest_type == VAR_LIST && tv_idx->v_type != VAR_NUMBER) + else if (dest_type == VAR_OBJECT && tv_idx->v_type == VAR_STRING) + { + // Need to get the member index now that the class is known. + object_T *obj = tv_dest->vval.v_object; + class_T *cl = obj->obj_class; + char_u *member = tv_idx->vval.v_string; + + ocmember_T *m = NULL; + for (int i = 0; i < cl->class_obj_member_count; ++i) + { + m = &cl->class_obj_members[i]; + if (STRCMP(member, m->ocm_name) == 0) + { + if (*member == '_') + { + semsg(_(e_cannot_access_private_member_str), + m->ocm_name); + status = FAIL; + } + + lidx = i; + break; + } + m = NULL; + } + + if (m == NULL) + { + semsg(_(e_member_not_found_on_object_str_str), + cl->class_name, member); + status = FAIL; + } + } + else if ((dest_type == VAR_LIST || dest_type == VAR_OBJECT) + && tv_idx->v_type != VAR_NUMBER) { emsg(_(e_number_expected)); status = FAIL; @@ -2151,7 +2189,6 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) { if (dest_type == VAR_LIST) { - long lidx = (long)tv_idx->vval.v_number; list_T *list = tv_dest->vval.v_list; if (list == NULL) @@ -2224,7 +2261,6 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) } else if (dest_type == VAR_BLOB) { - long lidx = (long)tv_idx->vval.v_number; blob_T *blob = tv_dest->vval.v_blob; varnumber_T nr; int error = FALSE; @@ -2255,18 +2291,17 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) } else if (dest_type == VAR_CLASS || dest_type == VAR_OBJECT) { - long idx = (long)tv_idx->vval.v_number; object_T *obj = tv_dest->vval.v_object; typval_T *otv = (typval_T *)(obj + 1); class_T *itf = iptr->isn_arg.storeindex.si_class; if (itf != NULL) // convert interface member index to class member index - idx = object_index_from_itf_index(itf, FALSE, - idx, obj->obj_class); + lidx = object_index_from_itf_index(itf, FALSE, + lidx, obj->obj_class); - clear_tv(&otv[idx]); - otv[idx] = *tv; + clear_tv(&otv[lidx]); + otv[lidx] = *tv; } else { |