# HG changeset patch # User Christian Brabandt # Date 1532312105 -7200 # Node ID d9e6eec551e1ea7f29b446d4346919d6f3e4943c # Parent 116b909126bd8f0b2ef2c20815f51795939f971b patch 8.1.0205: invalid memory access with invalid modeline commit https://github.com/vim/vim/commit/9cf4b5005f12ce1d6692266140bdda05d0312d79 Author: Bram Moolenaar Date: Mon Jul 23 04:12:03 2018 +0200 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 https://github.com/vim/vim/issues/3241) diff --git a/src/Make_all.mak b/src/Make_all.mak --- a/src/Make_all.mak +++ b/src/Make_all.mak @@ -118,6 +118,7 @@ NEW_TESTS = \ 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 --- a/src/option.c +++ b/src/option.c @@ -3316,7 +3316,7 @@ static char_u *set_bool_option(int opt_i 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 @@ 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 { @@ -4510,7 +4510,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 */ @@ -5362,7 +5362,7 @@ illegal_char(char_u *errbuf, int c) 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 @@ get_option_value( 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 @@ set_option_value( 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 @@ get_encoding_default(void) /* * Translate a string like "t_xx", "" or "" 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) -{ - int key; +find_key_option(char_u *arg_arg, int has_lt) +{ + 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 @@ 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 --- a/src/testdir/test_alot.vim +++ b/src/testdir/test_alot.vim @@ -37,6 +37,7 @@ source test_mapping.vim 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 --- /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 --- a/src/version.c +++ b/src/version.c @@ -794,6 +794,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 205, +/**/ 204, /**/ 203,