patch 7.4.1616
Problem:    Malformed channel request causes a hang.
Solution:   Drop malformed message. (Damien)
diff --git a/src/channel.c b/src/channel.c
index 2a71077..0d3f452 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1481,9 +1481,17 @@
      * TODO: insert in front */
     if (reader.js_buf[reader.js_used] != NUL)
     {
-	channel_save(channel, part, reader.js_buf + reader.js_used,
-		(int)(reader.js_end - reader.js_buf) - reader.js_used);
-	ret = TRUE;
+	if (ret == FAIL)
+	{
+	    ch_error(channel, "Decoding failed - discarding input");
+	    ret = FALSE;
+	}
+	else
+	{
+	    channel_save(channel, part, reader.js_buf + reader.js_used,
+		    (int)(reader.js_end - reader.js_buf) - reader.js_used);
+	    ret = TRUE;
+	}
     }
     else
 	ret = FALSE;
@@ -1586,12 +1594,14 @@
 
     if (STRCMP(cmd, "ex") == 0)
     {
+	ch_logs(channel, "Executing ex command '%s'", (char *)arg);
 	do_cmdline_cmd(arg);
     }
     else if (STRCMP(cmd, "normal") == 0)
     {
 	exarg_T ea;
 
+	ch_logs(channel, "Executing normal command '%s'", (char *)arg);
 	ea.arg = arg;
 	ea.addr_count = 0;
 	ea.forceit = TRUE; /* no mapping */
@@ -1601,6 +1611,7 @@
     {
 	exarg_T ea;
 
+	ch_log(channel, "redraw");
 	ea.forceit = *arg != NUL;
 	ex_redraw(&ea);
 	showruler(FALSE);
@@ -1642,11 +1653,18 @@
 	    /* Don't pollute the display with errors. */
 	    ++emsg_skip;
 	    if (!is_call)
+	    {
+		ch_logs(channel, "Evaluating expression '%s'", (char *)arg);
 		tv = eval_expr(arg, NULL);
-	    else if (func_call(arg, &argv[2], NULL, NULL, &res_tv) == OK)
-		tv = &res_tv;
+	    }
 	    else
-		tv = NULL;
+	    {
+		ch_logs(channel, "Calling '%s'", (char *)arg);
+		if (func_call(arg, &argv[2], NULL, NULL, &res_tv) == OK)
+		    tv = &res_tv;
+		else
+		    tv = NULL;
+	    }
 
 	    if (argv[id_idx].v_type == VAR_NUMBER)
 	    {
@@ -1848,10 +1866,7 @@
 
 	if (argv[0].v_type == VAR_STRING)
 	{
-	    char_u	*cmd = argv[0].vval.v_string;
-
 	    /* ["cmd", arg] or ["cmd", arg, arg] or ["cmd", arg, arg, arg] */
-	    ch_logs(channel, "Executing %s command", (char *)cmd);
 	    channel_exe_cmd(channel, part, argv);
 	    free_tv(listtv);
 	    return TRUE;
diff --git a/src/testdir/test_channel.py b/src/testdir/test_channel.py
index a465d65..47a12ea 100644
--- a/src/testdir/test_channel.py
+++ b/src/testdir/test_channel.py
@@ -104,6 +104,11 @@
                         print("sending: {}".format(cmd))
                         self.request.sendall(cmd.encode('utf-8'))
                         response = "ok"
+                    elif decoded[1] == 'malformed':
+                        cmd = '["ex",":"]wrong!["ex","smi"]'
+                        print("sending: {}".format(cmd))
+                        self.request.sendall(cmd.encode('utf-8'))
+                        response = "ok"
                     elif decoded[1] == 'an expr':
                         # Send an expr request.
                         cmd = '["expr","setline(\\"$\\", [\\"one\\",\\"two\\",\\"three\\"])"]'
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 6d38bff..c628bbe 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -123,10 +123,12 @@
     " check that no job is handled correctly
     call assert_equal('no process', string(ch_getjob(handle)))
   endif
-
   " Simple string request and reply.
   call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
 
+  " Malformed command should be ignored.
+  call assert_equal('ok', ch_evalexpr(handle, 'malformed'))
+
   " Request that triggers sending two ex commands.  These will usually be
   " handled before getting the response, but it's not guaranteed, thus wait a
   " tiny bit for the commands to get executed.
diff --git a/src/version.c b/src/version.c
index 2dbc176..c914ec4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1616,
+/**/
     1615,
 /**/
     1614,