diff src/vim9execute.c @ 23330:e8eb4fd44902 v8.2.2208

patch 8.2.2208: Vim9: after reloading a script variable index may be invalid Commit: https://github.com/vim/vim/commit/4aab88d919168ce2ddf4845482f4cff9efa52b5b Author: Bram Moolenaar <Bram@vim.org> Date: Thu Dec 24 21:56:41 2020 +0100 patch 8.2.2208: Vim9: after reloading a script variable index may be invalid Problem: Vim9: after reloading a script variable index may be invalid. Solution: When the sequence number doesn't match give an error for using a script-local variable from a compiled function. (closes #7547)
author Bram Moolenaar <Bram@vim.org>
date Thu, 24 Dec 2020 22:00:04 +0100
parents d9ae7dd3a0f2
children 456d625bb8c1
line wrap: on
line diff
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1402,12 +1402,21 @@ call_def_function(
 	    // load s: variable in Vim9 script
 	    case ISN_LOADSCRIPT:
 		{
-		    scriptitem_T *si =
-				  SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
+		    scriptref_T	*sref = iptr->isn_arg.script.scriptref;
+		    dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
+							  + ectx.ec_dfunc_idx;
+		    scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
 		    svar_T	 *sv;
 
-		    sv = ((svar_T *)si->sn_var_vals.ga_data)
-					     + iptr->isn_arg.script.script_idx;
+		    if (sref->sref_seq != si->sn_script_seq)
+		    {
+			// The script was reloaded after the function was
+			// compiled, the script_idx may not be valid.
+			semsg(_(e_script_variable_invalid_after_reload_in_function_str),
+						  dfunc->df_ufunc->uf_name_exp);
+			goto failed;
+		    }
+		    sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
 		    allocate_if_null(sv->sv_tv);
 		    if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
 			goto failed;
@@ -1616,11 +1625,22 @@ call_def_function(
 	    // store script-local variable in Vim9 script
 	    case ISN_STORESCRIPT:
 		{
-		    scriptitem_T *si = SCRIPT_ITEM(
-					      iptr->isn_arg.script.script_sid);
-		    svar_T	 *sv = ((svar_T *)si->sn_var_vals.ga_data)
-					     + iptr->isn_arg.script.script_idx;
-
+		    scriptref_T	*sref = iptr->isn_arg.script.scriptref;
+		    dfunc_T	*dfunc = ((dfunc_T *)def_functions.ga_data)
+							  + ectx.ec_dfunc_idx;
+		    scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
+		    svar_T	 *sv;
+
+		    if (sref->sref_seq != si->sn_script_seq)
+		    {
+			// The script was reloaded after the function was
+			// compiled, the script_idx may not be valid.
+			SOURCING_LNUM = iptr->isn_lnum;
+			semsg(_(e_script_variable_invalid_after_reload_in_function_str),
+						  dfunc->df_ufunc->uf_name_exp);
+			goto failed;
+		    }
+		    sv = ((svar_T *)si->sn_var_vals.ga_data) + sref->sref_idx;
 		    --ectx.ec_stack.ga_len;
 		    clear_tv(sv->sv_tv);
 		    *sv->sv_tv = *STACK_TV_BOT(0);
@@ -3378,14 +3398,14 @@ ex_disassemble(exarg_T *eap)
 		break;
 	    case ISN_LOADSCRIPT:
 		{
-		    scriptitem_T *si =
-				  SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
+		    scriptref_T	*sref = iptr->isn_arg.script.scriptref;
+		    scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
 		    svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
-					     + iptr->isn_arg.script.script_idx;
+							      + sref->sref_idx;
 
 		    smsg("%4d LOADSCRIPT %s-%d from %s", current,
 					    sv->sv_name,
-					    iptr->isn_arg.script.script_idx,
+					    sref->sref_idx,
 					    si->sn_name);
 		}
 		break;
@@ -3478,14 +3498,14 @@ ex_disassemble(exarg_T *eap)
 		break;
 	    case ISN_STORESCRIPT:
 		{
-		    scriptitem_T *si =
-				  SCRIPT_ITEM(iptr->isn_arg.script.script_sid);
+		    scriptref_T	*sref = iptr->isn_arg.script.scriptref;
+		    scriptitem_T *si = SCRIPT_ITEM(sref->sref_sid);
 		    svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data)
-					     + iptr->isn_arg.script.script_idx;
+							      + sref->sref_idx;
 
 		    smsg("%4d STORESCRIPT %s-%d in %s", current,
 					     sv->sv_name,
-					     iptr->isn_arg.script.script_idx,
+					     sref->sref_idx,
 					     si->sn_name);
 		}
 		break;