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