comparison src/vim9script.c @ 25358:f03271631eb5 v8.2.3216

patch 8.2.3216: Vim9: crash when using variable in a loop at script level Commit: https://github.com/vim/vim/commit/2eb6fc3b52148f961e804ec2be361d531ff770d8 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 25 14:13:53 2021 +0200 patch 8.2.3216: Vim9: crash when using variable in a loop at script level Problem: Vim9: crash when using variable in a loop at script level. Solution: Do not clear the variable if a function was defined. Do not create a new entry in sn_var_vals every time. (closes #8628)
author Bram Moolenaar <Bram@vim.org>
date Sun, 25 Jul 2021 14:15:04 +0200
parents 1e6da8364a02
children 3e56078569ca
comparison
equal deleted inserted replaced
25357:2cf7cefa5bfa 25358:f03271631eb5
756 type_T **type, 756 type_T **type,
757 int do_member) 757 int do_member)
758 { 758 {
759 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 759 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
760 hashitem_T *hi; 760 hashitem_T *hi;
761 svar_T *sv; 761 svar_T *sv = NULL;
762 762
763 if (create) 763 if (create)
764 { 764 {
765 sallvar_T *newsav; 765 sallvar_T *newsav;
766 sallvar_T *sav = NULL;
766 767
767 // Store a pointer to the typval_T, so that it can be found by index 768 // Store a pointer to the typval_T, so that it can be found by index
768 // instead of using a hastab lookup. 769 // instead of using a hastab lookup.
769 if (ga_grow(&si->sn_var_vals, 1) == FAIL) 770 if (ga_grow(&si->sn_var_vals, 1) == FAIL)
770 return; 771 return;
771 772
772 sv = ((svar_T *)si->sn_var_vals.ga_data) + si->sn_var_vals.ga_len; 773 hi = hash_find(&si->sn_all_vars.dv_hashtab, di->di_key);
773 newsav = (sallvar_T *)alloc_clear( 774 if (!HASHITEM_EMPTY(hi))
775 {
776 // Variable with this name exists, either in this block or in
777 // another block.
778 for (sav = HI2SAV(hi); ; sav = sav->sav_next)
779 {
780 if (sav->sav_block_id == si->sn_current_block_id)
781 {
782 // variable defined in a loop, re-use the entry
783 sv = ((svar_T *)si->sn_var_vals.ga_data)
784 + sav->sav_var_vals_idx;
785 // unhide the variable
786 if (sv->sv_tv == &sav->sav_tv)
787 {
788 clear_tv(&sav->sav_tv);
789 sv->sv_tv = &di->di_tv;
790 sav->sav_di = di;
791 }
792 break;
793 }
794 if (sav->sav_next == NULL)
795 break;
796 }
797 }
798
799 if (sv == NULL)
800 {
801 // Variable not defined or not defined in current block: Add a
802 // svar_T and create a new sallvar_T.
803 sv = ((svar_T *)si->sn_var_vals.ga_data) + si->sn_var_vals.ga_len;
804 newsav = (sallvar_T *)alloc_clear(
774 sizeof(sallvar_T) + STRLEN(di->di_key)); 805 sizeof(sallvar_T) + STRLEN(di->di_key));
775 if (newsav == NULL) 806 if (newsav == NULL)
776 return; 807 return;
777 808
778 sv->sv_tv = &di->di_tv; 809 sv->sv_tv = &di->di_tv;
779 sv->sv_const = (flags & ASSIGN_FINAL) ? ASSIGN_FINAL 810 sv->sv_const = (flags & ASSIGN_FINAL) ? ASSIGN_FINAL
780 : (flags & ASSIGN_CONST) ? ASSIGN_CONST : 0; 811 : (flags & ASSIGN_CONST) ? ASSIGN_CONST : 0;
781 sv->sv_export = is_export; 812 sv->sv_export = is_export;
782 newsav->sav_var_vals_idx = si->sn_var_vals.ga_len; 813 newsav->sav_var_vals_idx = si->sn_var_vals.ga_len;
783 ++si->sn_var_vals.ga_len; 814 ++si->sn_var_vals.ga_len;
784 STRCPY(&newsav->sav_key, di->di_key); 815 STRCPY(&newsav->sav_key, di->di_key);
785 sv->sv_name = newsav->sav_key; 816 sv->sv_name = newsav->sav_key;
786 newsav->sav_di = di; 817 newsav->sav_di = di;
787 newsav->sav_block_id = si->sn_current_block_id; 818 newsav->sav_block_id = si->sn_current_block_id;
788 819
789 hi = hash_find(&si->sn_all_vars.dv_hashtab, newsav->sav_key); 820 if (HASHITEM_EMPTY(hi))
790 if (!HASHITEM_EMPTY(hi)) 821 // new variable name
791 { 822 hash_add(&si->sn_all_vars.dv_hashtab, newsav->sav_key);
792 sallvar_T *sav = HI2SAV(hi); 823 else if (sav != NULL)
793 824 // existing name in a new block, append to the list
794 // variable with this name exists in another block 825 sav->sav_next = newsav;
795 while (sav->sav_next != NULL) 826 }
796 sav = sav->sav_next;
797 sav->sav_next = newsav;
798 }
799 else
800 // new variable name
801 hash_add(&si->sn_all_vars.dv_hashtab, newsav->sav_key);
802 } 827 }
803 else 828 else
804 { 829 {
805 sv = find_typval_in_script(&di->di_tv); 830 sv = find_typval_in_script(&di->di_tv);
806 } 831 }
807 if (sv != NULL) 832 if (sv != NULL)
808 { 833 {
809 if (*type == NULL) 834 if (*type == NULL)
810 *type = typval2type(tv, get_copyID(), &si->sn_type_list, 835 *type = typval2type(tv, get_copyID(), &si->sn_type_list, do_member);
811 do_member);
812 sv->sv_type = *type; 836 sv->sv_type = *type;
813 } 837 }
814 838
815 // let ex_export() know the export worked. 839 // let ex_export() know the export worked.
816 is_export = FALSE; 840 is_export = FALSE;