From c9af617ac62b15bfcbbfe8c54071146e2af01f65 Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Wed, 4 May 2022 16:46:54 +0100
Subject: [PATCH] patch 8.2.4863: accessing freed memory in test without the
 +channel feature
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

Problem:    Accessing freed memory in test without the +channel feature.
            (Dominique Pellé)
Solution:   Do not generted PUSHCHANNEL or PUSHJOB if they are not
            implemented. (closes #10350)
---
 src/errors.h                     |  4 ++++
 src/testdir/test_vim9_script.vim | 15 +++++++++++----
 src/version.c                    |  2 ++
 src/vim9compile.c                | 24 ++++++++++++++----------
 src/vim9instr.c                  | 14 ++++++++++++++
 5 files changed, 45 insertions(+), 14 deletions(-)

diff --git a/src/errors.h b/src/errors.h
index fc815ee31..2edbb63b9 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3264,4 +3264,8 @@ EXTERN char e_string_or_function_required_for_arrow_parens_expr[]
 	INIT(= N_("E1275: String or function required for ->(expr)"));
 EXTERN char e_illegal_map_mode_string_str[]
 	INIT(= N_("E1276: Illegal map mode string: '%s'"));
+# if !defined(FEAT_JOB_CHANNEL)
+EXTERN char e_channel_job_feature_not_available[]
+	INIT(= N_("E1277: Channel and job feature is not available"));
+# endif
 #endif
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 23b3502ce..33dd787b1 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -4132,8 +4132,10 @@ def Test_echo_uninit_variables()
   var Var_func: func
   var var_string: string
   var var_blob: blob
-  var var_job: job
-  var var_channel: channel
+  if has('job')
+    var var_job: job
+    var var_channel: channel
+  endif
   var var_list: list<any>
   var var_dict: dict<any>
 
@@ -4144,8 +4146,13 @@ def Test_echo_uninit_variables()
   echo Var_func
   echo var_string
   echo var_blob
-  echo var_job
-  echo var_channel
+  if has('job')
+    echo var_job
+    echo var_channel
+  else
+    echo 'no process'
+    echo 'channel fail'
+  endif
   echo var_list
   echo var_dict
   redir END
diff --git a/src/version.c b/src/version.c
index 5277fef5e..089994447 100644
--- a/src/version.c
+++ b/src/version.c
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4863,
 /**/
     4862,
 /**/
diff --git a/src/vim9compile.c b/src/vim9compile.c
index c1d5fb95b..8b22a8db2 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2293,39 +2293,41 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
 	    }
 	    else
 	    {
+		int r = OK;
+
 		// variables are always initialized
 		if (GA_GROW_FAILS(instr, 1))
 		    goto theend;
 		switch (lhs.lhs_member_type->tt_type)
 		{
 		    case VAR_BOOL:
-			generate_PUSHBOOL(cctx, VVAL_FALSE);
+			r = generate_PUSHBOOL(cctx, VVAL_FALSE);
 			break;
 		    case VAR_FLOAT:
 #ifdef FEAT_FLOAT
-			generate_PUSHF(cctx, 0.0);
+			r = generate_PUSHF(cctx, 0.0);
 #endif
 			break;
 		    case VAR_STRING:
-			generate_PUSHS(cctx, NULL);
+			r = generate_PUSHS(cctx, NULL);
 			break;
 		    case VAR_BLOB:
-			generate_PUSHBLOB(cctx, blob_alloc());
+			r = generate_PUSHBLOB(cctx, blob_alloc());
 			break;
 		    case VAR_FUNC:
-			generate_PUSHFUNC(cctx, NULL, &t_func_void);
+			r = generate_PUSHFUNC(cctx, NULL, &t_func_void);
 			break;
 		    case VAR_LIST:
-			generate_NEWLIST(cctx, 0, FALSE);
+			r = generate_NEWLIST(cctx, 0, FALSE);
 			break;
 		    case VAR_DICT:
-			generate_NEWDICT(cctx, 0, FALSE);
+			r = generate_NEWDICT(cctx, 0, FALSE);
 			break;
 		    case VAR_JOB:
-			generate_PUSHJOB(cctx);
+			r = generate_PUSHJOB(cctx);
 			break;
 		    case VAR_CHANNEL:
-			generate_PUSHCHANNEL(cctx);
+			r = generate_PUSHCHANNEL(cctx);
 			break;
 		    case VAR_NUMBER:
 		    case VAR_UNKNOWN:
@@ -2343,10 +2345,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
 			else
 			{
 			    instr_count = instr->ga_len;
-			    generate_PUSHNR(cctx, 0);
+			    r = generate_PUSHNR(cctx, 0);
 			}
 			break;
 		}
+		if (r == FAIL)
+		    goto theend;
 	    }
 	    if (var_count == 0)
 		end = p;
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 5a5e3c5ab..93ac062a3 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -755,12 +755,19 @@ generate_PUSHS(cctx_T *cctx, char_u **str)
     int
 generate_PUSHCHANNEL(cctx_T *cctx)
 {
+#ifdef FEAT_JOB_CHANNEL
     isn_T	*isn;
+#endif
 
     RETURN_OK_IF_SKIP(cctx);
+#ifdef FEAT_JOB_CHANNEL
     if ((isn = generate_instr_type(cctx, ISN_PUSHCHANNEL, &t_channel)) == NULL)
 	return FAIL;
     return OK;
+#else
+    emsg(_(e_channel_job_feature_not_available));
+    return FAIL;
+#endif
 }
 
 /*
@@ -769,12 +776,19 @@ generate_PUSHCHANNEL(cctx_T *cctx)
     int
 generate_PUSHJOB(cctx_T *cctx)
 {
+#ifdef FEAT_JOB_CHANNEL
     isn_T	*isn;
+#endif
 
     RETURN_OK_IF_SKIP(cctx);
+#ifdef FEAT_JOB_CHANNEL
     if ((isn = generate_instr_type(cctx, ISN_PUSHJOB, &t_job)) == NULL)
 	return FAIL;
     return OK;
+#else
+    emsg(_(e_channel_job_feature_not_available));
+    return FAIL;
+#endif
 }
 
 /*
-- 
2.40.0