patch 9.0.2149: [security]: use-after-free in exec_instructions()

Problem:  [security]: use-after-free in exec_instructions()
Solution: get tv pointer again

[security]: use-after-free in exec_instructions()

exec_instructions may access freed memory, if the GA_GROWS_FAILS()
re-allocates memory. When this happens, the typval tv may still point to
now already freed memory. So let's get that pointer again and compare it
with tv. If those two pointers differ, tv is now invalid and we have to
refresh the tv pointer.

closes: #13621

Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/vim9execute.c b/src/vim9execute.c
index e329559..44cdb09 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -4123,8 +4123,22 @@
 				      + iptr->isn_arg.outer.outer_idx;
 		    if (iptr->isn_type == ISN_LOADOUTER)
 		    {
+			typval_T *copy;
 			if (GA_GROW_FAILS(&ectx->ec_stack, 1))
 			    goto theend;
+			// careful: ga_grow_inner may re-alloc the stack
+			if (depth < 0)
+			    copy = ((typval_T *)outer->out_loop[-depth - 1]
+								   .stack->ga_data)
+					      + outer->out_loop[-depth - 1].var_idx
+					      + iptr->isn_arg.outer.outer_idx;
+			else
+			    copy = ((typval_T *)outer->out_stack->ga_data)
+					  + outer->out_frame_idx + STACK_FRAME_SIZE
+					  + iptr->isn_arg.outer.outer_idx;
+			// memory was freed, get tv again
+			if (copy != tv)
+			    tv = copy;
 			copy_tv(tv, STACK_TV_BOT(0));
 			++ectx->ec_stack.ga_len;
 		    }