From: Bram Moolenaar <Bram@vim.org>
Date: Mon, 23 Jul 2018 04:12:03 +0200
Subject: patch 8.1.0205: invalid memory access with invalid modeline

Problem:    Invalid memory access with invalid modeline.
Solution:   Pass pointer limit. Add a test. (closes #3241)

(cherry picked from commit 9cf4b5005f12ce1d6692266140bdda05d0312d79)

Signed-off-by: James McCoy <jamessan@debian.org>
---
 src/Makefile                  |  1 +
 src/option.c                  | 17 ++++++++++-------
 src/testdir/test_alot.vim     |  1 +
 src/testdir/test_modeline.vim |  8 ++++++++
 src/version.c                 |  2 ++
 5 files changed, 22 insertions(+), 7 deletions(-)
 create mode 100644 src/testdir/test_modeline.vim

diff --git a/src/Makefile b/src/Makefile
index 38ca4cd..53683a5 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2139,6 +2139,7 @@ test_arglist \
 	test_messages \
 	test_mksession \
 	test_mksession_utf8 \
+	test_modeline \
 	test_nested_function \
 	test_netbeans \
 	test_normal \
diff --git a/src/option.c b/src/option.c
index 056292f..48bf9ce 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3144,7 +3144,7 @@ static char_u *set_bool_option(int opt_idx, char_u *varp, int value, int opt_fla
 static char_u *set_num_option(int opt_idx, char_u *varp, long value, char_u *errbuf, size_t errbuflen, int opt_flags);
 static void check_redraw(long_u flags);
 static int findoption(char_u *);
-static int find_key_option(char_u *);
+static int find_key_option(char_u *arg_arg, int has_lt);
 static void showoptions(int all, int opt_flags);
 static int optval_default(struct vimoption *, char_u *varp);
 static void showoneopt(struct vimoption *, int opt_flags);
@@ -4279,7 +4279,7 @@ do_set(
 		    opt_idx = findoption(arg + 1);
 		arg[len++] = '>';		    /* restore '>' */
 		if (opt_idx == -1)
-		    key = find_key_option(arg + 1);
+		    key = find_key_option(arg + 1, TRUE);
 	    }
 	    else
 	    {
@@ -4297,7 +4297,7 @@ do_set(
 		opt_idx = findoption(arg);
 		arg[len] = nextchar;		    /* restore nextchar */
 		if (opt_idx == -1)
-		    key = find_key_option(arg);
+		    key = find_key_option(arg, FALSE);
 	    }
 
 	    /* remember character after option name */
@@ -5147,7 +5147,7 @@ illegal_char(char_u *errbuf, int c)
 string_to_key(char_u *arg)
 {
     if (*arg == '<')
-	return find_key_option(arg + 1);
+	return find_key_option(arg + 1, TRUE);
     if (*arg == '^')
 	return Ctrl_chr(arg[1]);
     return *arg;
@@ -9531,12 +9531,15 @@ get_encoding_default(void)
 
 /*
  * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
+ * When "has_lt" is true there is a '<' before "*arg_arg".
+ * Returns 0 when the key is not recognized.
  */
     static int
-find_key_option(char_u *arg)
+find_key_option(char_u *arg_arg, int has_lt)
 {
-    int		key;
+    int		key = 0;
     int		modifiers;
+    char_u	*arg = arg_arg;
 
     /*
      * Don't use get_special_key_code() for t_xx, we don't want it to call
@@ -9544,7 +9547,7 @@ find_key_option(char_u *arg)
      */
     if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3])
 	key = TERMCAP2KEY(arg[2], arg[3]);
-    else
+    else if (has_lt)
     {
 	--arg;			    /* put arg at the '<' */
 	modifiers = 0;
diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim
index 9a7c35d..9dadf6f 100644
--- a/src/testdir/test_alot.vim
+++ b/src/testdir/test_alot.vim
@@ -29,6 +29,7 @@ source test_match.vim
 source test_menu.vim
 source test_mapping.vim
 source test_messages.vim
+source test_modeline.vim
 source test_partial.vim
 source test_popup.vim
 source test_reltime.vim
diff --git a/src/testdir/test_modeline.vim b/src/testdir/test_modeline.vim
new file mode 100644
index 0000000..6e49577
--- /dev/null
+++ b/src/testdir/test_modeline.vim
@@ -0,0 +1,8 @@
+" Tests for parsing the modeline.
+
+func Test_invalid()
+  " This was reading before allocated memory.
+  call writefile(['vi:0', 'nothing'], 'Xmodeline')
+  call assert_fails('split Xmodeline', 'E518:')
+  bwipe!
+endfunc
diff --git a/src/version.c b/src/version.c
index 56a66d2..fc88f3d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -1195,6 +1195,8 @@ static int included_patches[] =
  */
 static char *(extra_patches[]) =
 {   /* Add your patch description below this line */
+/**/
+    "8.1.0205",
 /**/
     "8.1.0189",
 /**/
