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)
diff --git a/src/Make_all.mak b/src/Make_all.mak
index ef30503..9831f7b 100644
--- a/src/Make_all.mak
+++ b/src/Make_all.mak
@@ -118,6 +118,7 @@
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 6d86183..f86b1b1 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3316,7 +3316,7 @@
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);
@@ -4492,7 +4492,7 @@
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
{
@@ -4510,7 +4510,7 @@
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 */
@@ -5362,7 +5362,7 @@
string_to_key(char_u *arg, int multi_byte)
{
if (*arg == '<')
- return find_key_option(arg + 1);
+ return find_key_option(arg + 1, TRUE);
if (*arg == '^')
return Ctrl_chr(arg[1]);
if (multi_byte)
@@ -9541,7 +9541,7 @@
int key;
if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
- && (key = find_key_option(name)) != 0)
+ && (key = find_key_option(name, FALSE)) != 0)
{
char_u key_name[2];
char_u *p;
@@ -9831,7 +9831,7 @@
int key;
if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
- && (key = find_key_option(name)) != 0)
+ && (key = find_key_option(name, FALSE)) != 0)
{
char_u key_name[2];
@@ -9952,12 +9952,15 @@
/*
* 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
@@ -9965,7 +9968,7 @@
*/
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 ac3ca74..1465a7a 100644
--- a/src/testdir/test_alot.vim
+++ b/src/testdir/test_alot.vim
@@ -37,6 +37,7 @@
source test_match.vim
source test_menu.vim
source test_messages.vim
+source test_modeline.vim
source test_partial.vim
source test_popup.vim
source test_put.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 735ac0e..23fea92 100644
--- a/src/version.c
+++ b/src/version.c
@@ -794,6 +794,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 205,
+/**/
204,
/**/
203,