Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Please unblock package neovim

This upload contains the rest of the fixes needed to address
CVE-2019-12735/#930024.

unblock neovim/0.3.4-3

-- System Information:
Debian Release: 10.0
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'unstable'), (1, 
'experimental-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-5-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diffstat for neovim-0.3.4 neovim-0.3.4

 changelog                                                               |   28 
 patches/0001-debcherry-fixup-patch.patch                                | 1066 
++++++++++
 patches/0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch |   36 
 patches/0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch |   36 
 patches/0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch |  104 
 patches/0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch |   41 
 patches/0005-vim-patch-8.1.0206-duplicate-test-function-name.patch      |   35 
 patches/0006-vim-patch-8.1.1382-error-when-editing-test-file.patch      |   59 
 patches/0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch |   57 
 patches/series                                                          |    8 
 10 files changed, 1433 insertions(+), 37 deletions(-)

diff -Nru neovim-0.3.4/debian/changelog neovim-0.3.4/debian/changelog
--- neovim-0.3.4/debian/changelog       2019-06-05 21:38:14.000000000 -0400
+++ neovim-0.3.4/debian/changelog       2019-06-26 21:21:33.000000000 -0400
@@ -1,3 +1,31 @@
+neovim (0.3.4-3) unstable; urgency=high
+
+  * Backport additional changes to address CVE-2019-12735 (Closes: #930024)
+    + vim-patch:8.1.0177: defining function in sandbox is inconsistent
+    + vim-patch:8.1.0189: function defined in sandbox not tested
+    + vim-patch:8.1.0538: evaluating a modeline might invoke using a shell
+      command
+    + vim-patch:8.1.0539: cannot build without the sandbox
+    + vim-patch:8.1.0540: may evaluate insecure value when appending to option
+    + vim-patch:8.1.0544: setting 'filetype' in a modeline causes an error
+    + vim-patch:8.1.0613: when executing an insecure function the secure flag
+      is stuck
+    + vim-patch:8.1.1046: the "secure" variable is used inconsistently
+    + vim-patch:8.1.0205: invalid memory access with invalid modeline
+    + vim-patch:8.1.0206: duplicate test function name
+    + vim-patch:8.1.0506: modeline test fails when run by root
+    + vim-patch:8.1.0546: modeline test with keymap fails
+    + vim-patch:8.1.0547: modeline test with keymap still fails
+    + vim-patch:8.1.1366: using expressions in a modeline is unsafe
+    + vim-patch:8.1.1367: can set 'modelineexpr' in modeline
+    + vim-patch:8.1.1368: modeline test fails with python but without
+      pythonhome
+    + vim-patch:8.1.1382: error when editing test file
+    + vim-patch:8.1.1401: misspelled mkspellmem as makespellmem
+  * Backport patch to prevent use of nvim's API within the sandbox
+
+ -- James McCoy <james...@debian.org>  Wed, 26 Jun 2019 21:21:33 -0400
+
 neovim (0.3.4-2) unstable; urgency=high
 
   [ Efraim Flashner ]
diff -Nru neovim-0.3.4/debian/patches/0001-debcherry-fixup-patch.patch 
neovim-0.3.4/debian/patches/0001-debcherry-fixup-patch.patch
--- neovim-0.3.4/debian/patches/0001-debcherry-fixup-patch.patch        
1969-12-31 19:00:00.000000000 -0500
+++ neovim-0.3.4/debian/patches/0001-debcherry-fixup-patch.patch        
2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,1066 @@
+From d39c384696e94bd8cb4a8830f0ec2e801619a970 Mon Sep 17 00:00:00 2001
+From: James McCoy <james...@jamessan.com>
+Date: Wed, 26 Jun 2019 21:32:44 -0400
+Subject: [PATCH 1/7] debcherry fixup patch
+
+ed179f931 vim-patch:8.1.1401: misspelled mkspellmem as makespellmem
+        - no changes against upstream or conflicts
+41a3ff9fe vim-patch:8.1.1368: modeline test fails with python but without 
pythonhome
+        - no changes against upstream or conflicts
+12c5b6885 vim-patch:8.1.1367: can set 'modelineexpr' in modeline
+        - no changes against upstream or conflicts
+cffc3f5f8 vim-patch:8.1.1366: using expressions in a modeline is unsafe
+        - extra changes or conflicts
+a15defc3c vim-patch:8.1.0547: modeline test with keymap still fails
+        - extra changes or conflicts
+c550a5e94 vim-patch:8.1.0546: modeline test with keymap fails
+        - no changes against upstream or conflicts
+0605eb856 vim-patch:8.1.0506: modeline test fails when run by root
+        - no changes against upstream or conflicts
+cbec04e98 vim-patch:8.1.0205: invalid memory access with invalid modeline
+        - extra changes or conflicts
+ed7ca8f1e vim-patch:8.1.1046: the "secure" variable is used inconsistently
+        - no changes against upstream or conflicts
+4f223fb12 vim-patch:8.1.0613: when executing an insecure function the secure 
flag is stuck
+        - extra changes or conflicts
+4fc181350 fixup: use vim_snprintf, ASCII_ISALNUM
+        - no changes against upstream or conflicts
+2789ea195 vim-patch:8.1.0544: setting 'filetype' in a modeline causes an error
+        - extra changes or conflicts
+94b32dd17 vim-patch:8.1.0540: may evaluate insecure value when appending to 
option
+        - extra changes or conflicts
+a36f7e776 vim-patch:8.1.0539: cannot build without the sandbox
+        - extra changes or conflicts
+b1ab0ee1a vim-patch:8.1.0538: evaluating a modeline might invoke using a shell 
command
+        - extra changes or conflicts
+bc4e31de5 vim-patch:8.0.0003
+        - no changes against upstream or conflicts
+53bde37a8 vim-patch:8.0.0376
+        - extra changes or conflicts
+aa0c704e7 vim-patch:8.0.0322
+        - extra changes or conflicts
+29b888573 vim-patch:8.0.0057
+        - no changes against upstream or conflicts
+fb1670cdd vim-patch:8.0.0056
+        - extra changes or conflicts
+---
+ runtime/doc/options.txt             |  75 +++++++++---
+ src/nvim/buffer.c                   |   6 +
+ src/nvim/generators/gen_options.lua |   1 +
+ src/nvim/option.c                   | 177 +++++++++++++++++++---------
+ src/nvim/option_defs.h              |   1 +
+ src/nvim/options.lua                |  21 ++++
+ src/nvim/testdir/test49.in          |   2 +-
+ src/nvim/testdir/test_alot.vim      |   1 +
+ src/nvim/testdir/test_autocmd.vim   |  23 ++++
+ src/nvim/testdir/test_modeline.vim  | 173 +++++++++++++++++++++++++++
+ 10 files changed, 406 insertions(+), 74 deletions(-)
+ create mode 100644 src/nvim/testdir/test_modeline.vim
+
+diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
+index 534b2025c..e8471d561 100644
+--- a/runtime/doc/options.txt
++++ b/runtime/doc/options.txt
+@@ -478,14 +478,17 @@ backslash in front of the ':' will be removed.  Example:
+    /* vi:set dir=c\:\tmp: */ ~
+ This sets the 'dir' option to "c:\tmp".  Only a single backslash before the
+ ':' is removed.  Thus to include "\:" you have to specify "\\:".
+-
++                                                      *E992*
+ No other commands than "set" are supported, for security reasons (somebody
+ might create a Trojan horse text file with modelines).  And not all options
+-can be set.  For some options a flag is set, so that when it's used the
+-|sandbox| is effective.  Still, there is always a small risk that a modeline
+-causes trouble.  E.g., when some joker sets 'textwidth' to 5 all your lines
+-are wrapped unexpectedly.  So disable modelines before editing untrusted text.
+-The mail ftplugin does this, for example.
++can be set.  For some options a flag is set, so that when the value is used
++the |sandbox| is effective.  Some options can only be set from the modeline
++when 'modelineexpr' is set (the default is off).
++
++Still, there is always a small risk that a modeline causes trouble.  E.g.,
++when some joker sets 'textwidth' to 5 all your lines are wrapped unexpectedly.
++So disable modelines before editing untrusted text.  The mail ftplugin does
++this, for example.
+ 
+ Hint: If you would like to do something else than setting an option, you could
+ define an autocommand that checks the file for a specific string.  For
+@@ -2439,7 +2442,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       The expression will be evaluated in the |sandbox| if set from a
+       modeline, see |sandbox-option|.
+       This option can't be set from a |modeline| when the 'diff' option is
+-      on.
++      on or the 'modelineexpr' option is off.
+ 
+       It is not allowed to change text or jump to another window while
+       evaluating 'foldexpr' |textlock|.
+@@ -2554,6 +2557,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ 
+       The expression will be evaluated in the |sandbox| if set from a
+       modeline, see |sandbox-option|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+       It is not allowed to change text or jump to another window while
+       evaluating 'foldtext' |textlock|.
+@@ -2589,16 +2593,8 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       The expression will be evaluated in the |sandbox| when set from a
+       modeline, see |sandbox-option|.  That stops the option from working,
+       since changing the buffer text is not allowed.
+-
+-                                      *'formatoptions'* *'fo'*
+-'formatoptions' 'fo'  string (default: "tcqj", Vi default: "vt")
+-                      local to buffer
+-      This is a sequence of letters which describes how automatic
+-      formatting is to be done.  See |fo-table|.  When the 'paste' option is
+-      on, no formatting is done (like 'formatoptions' is empty).  Commas can
+-      be inserted for readability.
+-      To avoid problems with flags that are added in the future, use the
+-      "+=" and "-=" feature of ":set" |add-option-flags|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
++      NOTE: This option is set to "" when 'compatible' is set.
+ 
+                                       *'formatlistpat'* *'flp'*
+ 'formatlistpat' 'flp' string (default: "^\s*\d\+[\]:.)}\t ]\s*")
+@@ -2613,6 +2609,16 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       The default recognizes a number, followed by an optional punctuation
+       character and white space.
+ 
++                                      *'formatoptions'* *'fo'*
++'formatoptions' 'fo'  string (default: "tcqj", Vi default: "vt")
++                      local to buffer
++      This is a sequence of letters which describes how automatic
++      formatting is to be done.  See |fo-table|.  When the 'paste' option is
++      on, no formatting is done (like 'formatoptions' is empty).  Commas can
++      be inserted for readability.
++      To avoid problems with flags that are added in the future, use the
++      "+=" and "-=" feature of ":set" |add-option-flags|.
++
+                                               *'formatprg'* *'fp'*
+ 'formatprg' 'fp'      string (default "")
+                       global or local to buffer |global-local|
+@@ -2643,6 +2649,9 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       - system signals low battery life
+       - Nvim exits abnormally
+ 
++      This option cannot be set from a |modeline| or in the |sandbox|, for
++      security reasons.
++
+                                  *'gdefault'* *'gd'* *'nogdefault'* *'nogd'*
+ 'gdefault' 'gd'               boolean (default off)
+                       global
+@@ -2978,6 +2987,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       'guitabtooltip' is used for the tooltip, see below.
+       The expression will be evaluated in the |sandbox| when set from a
+       modeline, see |sandbox-option|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+       Only used when the GUI tab pages line is displayed.  'e' must be
+       present in 'guioptions'.  For the non-GUI tab pages line 'tabline' is
+@@ -3106,6 +3116,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       When this option contains printf-style '%' items, they will be
+       expanded according to the rules used for 'statusline'.  See
+       'titlestring' for example settings.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+                       *'ignorecase'* *'ic'* *'noignorecase'* *'noic'*
+ 'ignorecase' 'ic'     boolean (default off)
+@@ -3209,6 +3220,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ 
+       The expression will be evaluated in the |sandbox| when set from a
+       modeline, see |sandbox-option|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+       It is not allowed to change text or jump to another window while
+       evaluating 'includeexpr' |textlock|.
+@@ -3277,6 +3289,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ 
+       The expression will be evaluated in the |sandbox| when set from a
+       modeline, see |sandbox-option|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+       It is not allowed to change text or jump to another window while
+       evaluating 'indentexpr' |textlock|.
+@@ -3879,10 +3892,23 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ <     If you have less than 512 Mbyte |:mkspell| may fail for some
+       languages, no matter what you set 'mkspellmem' to.
+ 
++      This option cannot be set from a |modeline| or in the |sandbox|.
++
+                                  *'modeline'* *'ml'* *'nomodeline'* *'noml'*
+ 'modeline' 'ml'               boolean (Vim default: on (off for root),
+                                Vi default: off)
+                       local to buffer
++      If 'modeline' is on 'modelines' gives the number of lines that is
++      checked for set commands.  If 'modeline' is off or 'modelines' is zero
++      no lines are checked.  See |modeline|.
++
++                         *'modelineexpr'* *'mle'* *'nomodelineexpr'* *'nomle'*
++'modelineexpr' 'mle'  boolean (default: off)
++                      global
++      When on allow some options that are an expression to be set in the
++      modeline.  Check the option for whether it is affected by
++      'modelineexpr'.  Also see |modeline|.
++
+                                               *'modelines'* *'mls'*
+ 'modelines' 'mls'     number  (default 5)
+                       global
+@@ -4622,6 +4648,8 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       When this option is not empty, it determines the content of the ruler
+       string, as displayed for the 'ruler' option.
+       The format of this option is like that of 'statusline'.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
++
+       The default ruler width is 17 characters.  To make the ruler 15
+       characters wide, put "%15(" at the start and "%)" at the end.
+       Example: >
+@@ -5252,7 +5280,8 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+               "Pattern not found", "Back at original", etc.
+         q     use "recording" instead of "recording @a"
+         F     don't give the file info when editing a file, like `:silent`
+-              was used for the command
++              was used for the command; note that this also affects messages
++              from autocommands
+ 
+       This gives you the opportunity to avoid that a change between buffers
+       requires you to hit <Enter>, but still gives as useful a message as
+@@ -5527,7 +5556,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ 
+       After this option has been set successfully, Vim will source the files
+       "spell/LANG.vim" in 'runtimepath'.  "LANG" is the value of 'spelllang'
+-      up to the first comma, dot or underscore.
++      up to the first character that is not an ASCII letter and not a dash.
+       Also see |set-spc-auto|.
+ 
+ 
+@@ -5773,6 +5802,7 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+ 
+       The 'statusline' option will be evaluated in the |sandbox| if set from
+       a modeline, see |sandbox-option|.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
+ 
+       It is not allowed to change text or jump to another window while
+       evaluating 'statusline' |textlock|.
+@@ -5927,6 +5957,8 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       the text to be displayed.  Use "%1T" for the first label, "%2T" for
+       the second one, etc.  Use "%X" items for closing labels.
+ 
++      This option cannot be set in a modeline when 'modelineexpr' is off.
++
+       Keep in mind that only one of the tab pages is the current one, others
+       are invisible and you can't jump to their windows.
+ 
+@@ -6203,8 +6235,11 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+                       global
+       When this option is not empty, it will be used for the title of the
+       window.  This happens only when the 'title' option is on.
++
+       When this option contains printf-style '%' items, they will be
+       expanded according to the rules used for 'statusline'.
++      This option cannot be set in a modeline when 'modelineexpr' is off.
++
+       Example: >
+           :auto BufEnter * let &titlestring = hostname() . "/" . expand("%:p")
+           :set title titlestring=%<%F%=%l/%L-%P titlelen=70
+@@ -6238,6 +6273,8 @@ A jump table for the options with a short description 
can be found at |Q_op|.
+       undo file that exists is used.  When it cannot be read an error is
+       given, no further entry is used.
+       See |undo-persistence|.
++      This option cannot be set from a |modeline| or in the |sandbox|, for
++      security reasons.
+ 
+                               *'undofile'* *'noundofile'* *'udf'* *'noudf'*
+ 'undofile' 'udf'      boolean (default off)
+diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
+index 8b107041b..99e910d15 100644
+--- a/src/nvim/buffer.c
++++ b/src/nvim/buffer.c
+@@ -4923,9 +4923,15 @@ chk_modeline (
+     *e = NUL;                         /* truncate the set command */
+ 
+     if (*s != NUL) {                  /* skip over an empty "::" */
++      const int secure_save = secure;
+       save_SID = current_SID;
+       current_SID = SID_MODELINE;
++      // Make sure no risky things are executed as a side effect.
++      secure = 1;
++
+       retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags);
++
++      secure = secure_save;
+       current_SID = save_SID;
+       if (retval == FAIL)                     /* stop if error found */
+         break;
+diff --git a/src/nvim/generators/gen_options.lua 
b/src/nvim/generators/gen_options.lua
+index fdc00d5dc..d9c65e17c 100644
+--- a/src/nvim/generators/gen_options.lua
++++ b/src/nvim/generators/gen_options.lua
+@@ -79,6 +79,7 @@ local get_flags = function(o)
+     {'pri_mkrc'},
+     {'deny_in_modelines', 'P_NO_ML'},
+     {'deny_duplicates', 'P_NODUP'},
++    {'modelineexpr', 'P_MLE'},
+   }) do
+     local key_name = flag_desc[1]
+     local def_name = flag_desc[2] or ('P_' .. key_name:upper())
+diff --git a/src/nvim/option.c b/src/nvim/option.c
+index 8c692f9f4..d36a5de20 100644
+--- a/src/nvim/option.c
++++ b/src/nvim/option.c
+@@ -251,6 +251,7 @@ typedef struct vimoption {
+ #define P_RWINONLY     0x10000000U  ///< only redraw current window
+ #define P_NDNAME       0x20000000U  ///< only normal dir name chars allowed
+ #define P_UI_OPTION    0x40000000U  ///< send option to remote ui
++#define P_MLE          0x80000000U  ///< under control of 'modelineexpr'
+ 
+ #define HIGHLIGHT_INIT \
+   "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
+@@ -1200,7 +1201,7 @@ do_set (
+         }
+         len++;
+         if (opt_idx == -1) {
+-          key = find_key_option(arg + 1);
++          key = find_key_option(arg + 1, true);
+         }
+       } else {
+         len = 0;
+@@ -1214,7 +1215,7 @@ do_set (
+         }
+         opt_idx = findoption_len((const char *)arg, (size_t)len);
+         if (opt_idx == -1) {
+-          key = find_key_option(arg);
++          key = find_key_option(arg, false);
+         }
+       }
+ 
+@@ -1281,6 +1282,11 @@ do_set (
+           errmsg = (char_u *)_("E520: Not allowed in a modeline");
+           goto skip;
+         }
++        if ((flags & P_MLE) && !p_mle) {
++          errmsg = (char_u *)_(
++              "E992: Not allowed in a modeline when 'modelineexpr' is off");
++          goto skip;
++        }
+         /* In diff mode some options are overruled.  This avoids that
+          * 'foldmethod' becomes "marker" instead of "diff" and that
+          * "wrap" gets set. */
+@@ -1355,6 +1361,10 @@ do_set (
+             && nextchar != NUL && !ascii_iswhite(afterchar))
+           errmsg = e_trailing;
+       } else {
++
++        int value_is_replaced = !prepending && !adding && !removing;
++        int value_checked = false;
++
+         if (flags & P_BOOL) {                       /* boolean */
+           if (nextchar == '=' || nextchar == ':') {
+             errmsg = e_invarg;
+@@ -1774,12 +1784,32 @@ do_set (
+             // buffer is closed by autocommands.
+             saved_newval = (newval != NULL) ? xstrdup((char *)newval) : 0;
+ 
+-            // Handle side effects, and set the global value for
+-            // ":set" on local options. Note: when setting 'syntax'
+-            // or 'filetype' autocommands may be triggered that can
+-            // cause havoc.
+-            errmsg = did_set_string_option(opt_idx, (char_u **)varp,
+-                new_value_alloced, oldval, errbuf, opt_flags);
++            {
++              uint32_t *p = insecure_flag(opt_idx, opt_flags);
++              const int secure_saved = secure;
++
++              // When an option is set in the sandbox, from a
++              // modeline or in secure mode, then deal with side
++              // effects in secure mode.  Also when the value was
++              // set with the P_INSECURE flag and is not
++              // completely replaced.
++              if ((opt_flags & OPT_MODELINE)
++                  || sandbox != 0
++                  || (!value_is_replaced && (*p & P_INSECURE))) {
++                secure = 1;
++              }
++
++              // Handle side effects, and set the global value
++              // for ":set" on local options. Note: when setting
++              // 'syntax' or 'filetype' autocommands may be
++              // triggered that can cause havoc.
++              errmsg = did_set_string_option(opt_idx, (char_u **)varp,
++                                             new_value_alloced, oldval,
++                                             errbuf, sizeof(errbuf),
++                                             opt_flags, &value_checked);
++
++              secure = secure_saved;
++            }
+ 
+             if (errmsg == NULL) {
+               if (!starting) {
+@@ -1806,8 +1836,7 @@ do_set (
+         }
+ 
+         if (opt_idx >= 0)
+-          did_set_option(opt_idx, opt_flags,
+-              !prepending && !adding && !removing);
++          did_set_option(opt_idx, opt_flags, value_is_replaced, 
value_checked);
+       }
+ 
+ skip:
+@@ -1872,7 +1901,9 @@ static void
+ did_set_option (
+     int opt_idx,
+     int opt_flags,              /* possibly with OPT_MODELINE */
+-    int new_value              /* value was replaced completely */
++    int new_value,              /* value was replaced completely */
++    int value_checked           /* value was checked to be safe, no need to
++                                   set P_INSECURE */
+ )
+ {
+   options[opt_idx].flags |= P_WAS_SET;
+@@ -1881,20 +1912,22 @@ did_set_option (
+    * set the P_INSECURE flag.  Otherwise, if a new value is stored reset the
+    * flag. */
+   uint32_t *p = insecure_flag(opt_idx, opt_flags);
+-  if (secure
+-      || sandbox != 0
+-      || (opt_flags & OPT_MODELINE))
++  if (!value_checked && (secure
++                         || sandbox != 0
++                         || (opt_flags & OPT_MODELINE))) {
+     *p = *p | P_INSECURE;
+-  else if (new_value)
++  } else if (new_value) {
+     *p = *p & ~P_INSECURE;
++  }
+ }
+ 
+-static char_u *illegal_char(char_u *errbuf, int c)
++static char_u *illegal_char(char_u *errbuf, size_t errbuflen, int c)
+ {
+-  if (errbuf == NULL)
++  if (errbuf == NULL) {
+     return (char_u *)"";
+-  sprintf((char *)errbuf, _("E539: Illegal character <%s>"),
+-      (char *)transchar(c));
++  }
++  vim_snprintf((char *)errbuf, errbuflen, _("E539: Illegal character <%s>"),
++               (char *)transchar(c));
+   return errbuf;
+ }
+ 
+@@ -1904,10 +1937,12 @@ static char_u *illegal_char(char_u *errbuf, int c)
+  */
+ static int string_to_key(char_u *arg)
+ {
+-  if (*arg == '<')
+-    return find_key_option(arg + 1);
+-  if (*arg == '^')
++  if (*arg == '<') {
++    return find_key_option(arg + 1, true);
++  }
++  if (*arg == '^') {
+     return Ctrl_chr(arg[1]);
++  }
+   return *arg;
+ }
+ 
+@@ -2383,10 +2418,12 @@ static char *set_string_option(const int opt_idx, 
const char *const value,
+   char *const saved_oldval = xstrdup(oldval);
+   char *const saved_newval = xstrdup(s);
+ 
++  int value_checked = false;
+   char *const r = (char *)did_set_string_option(
+-      opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, NULL, opt_flags);
++      opt_idx, (char_u **)varp, (int)true, (char_u *)oldval,
++      NULL, 0, opt_flags, &value_checked);
+   if (r == NULL) {
+-    did_set_option(opt_idx, opt_flags, true);
++    did_set_option(opt_idx, opt_flags, true, value_checked);
+   }
+ 
+   // call autocommand after handling side effects
+@@ -2427,13 +2464,16 @@ static bool valid_filetype(char_u *val)
+  * Returns NULL for success, or an error message for an error.
+  */
+ static char_u *
+-did_set_string_option (
+-    int opt_idx,                            /* index in options[] table */
+-    char_u **varp,                     /* pointer to the option variable */
+-    int new_value_alloced,                  /* new value was allocated */
+-    char_u *oldval,                    /* previous value of the option */
+-    char_u *errbuf,                    /* buffer for errors, or NULL */
+-    int opt_flags                          /* OPT_LOCAL and/or OPT_GLOBAL */
++did_set_string_option(
++    int opt_idx,                       // index in options[] table
++    char_u **varp,                     // pointer to the option variable
++    int new_value_alloced,             // new value was allocated
++    char_u *oldval,                    // previous value of the option
++    char_u *errbuf,                    // buffer for errors, or NULL
++    size_t errbuflen,                  // length of errors buffer
++    int opt_flags,                     // OPT_LOCAL and/or OPT_GLOBAL
++    int *value_checked                 // value was checked to be safe, no
++                                       // need to set P_INSECURE
+ )
+ {
+   char_u      *errmsg = NULL;
+@@ -2651,8 +2691,20 @@ did_set_string_option (
+     if (!valid_filetype(*varp)) {
+       errmsg = e_invarg;
+     } else {
++      int secure_save = secure;
++
++      // Reset the secure flag, since the value of 'keymap' has
++      // been checked to be safe.
++      secure = 0;
++
+       // load or unload key mapping tables
+       errmsg = keymap_init();
++
++      secure = secure_save;
++
++      // Since we check the value, there is no need to set P_INSECURE,
++      // even when the value comes from a modeline.
++      *value_checked = true;
+     }
+ 
+     if (errmsg == NULL) {
+@@ -2738,7 +2790,7 @@ did_set_string_option (
+       while (*s && *s != ':') {
+         if (vim_strchr((char_u *)COM_ALL, *s) == NULL
+             && !ascii_isdigit(*s) && *s != '-') {
+-          errmsg = illegal_char(errbuf, *s);
++          errmsg = illegal_char(errbuf, errbuflen, *s);
+           break;
+         }
+         ++s;
+@@ -2790,7 +2842,7 @@ did_set_string_option (
+     for (s = p_shada; *s; ) {
+       /* Check it's a valid character */
+       if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) {
+-        errmsg = illegal_char(errbuf, *s);
++        errmsg = illegal_char(errbuf, errbuflen, *s);
+         break;
+       }
+       if (*s == 'n') {          /* name is always last one */
+@@ -2810,9 +2862,9 @@ did_set_string_option (
+ 
+         if (!ascii_isdigit(*(s - 1))) {
+           if (errbuf != NULL) {
+-            sprintf((char *)errbuf,
+-                _("E526: Missing number after <%s>"),
+-                transchar_byte(*(s - 1)));
++            vim_snprintf((char *)errbuf, errbuflen,
++                         _("E526: Missing number after <%s>"),
++                         transchar_byte(*(s - 1)));
+             errmsg = errbuf;
+           } else
+             errmsg = (char_u *)"";
+@@ -2990,7 +3042,7 @@ did_set_string_option (
+       if (!*s)
+         break;
+       if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL) {
+-        errmsg = illegal_char(errbuf, *s);
++        errmsg = illegal_char(errbuf, errbuflen, *s);
+         break;
+       }
+       if (*++s != NUL && *s != ',' && *s != ' ') {
+@@ -3004,9 +3056,9 @@ did_set_string_option (
+           }
+         } else {
+           if (errbuf != NULL) {
+-            sprintf((char *)errbuf,
+-                _("E535: Illegal character after <%c>"),
+-                *--s);
++            vim_snprintf((char *)errbuf, errbuflen,
++                         _("E535: Illegal character after <%c>"),
++                         *--s);
+             errmsg = errbuf;
+           } else
+             errmsg = (char_u *)"";
+@@ -3163,12 +3215,20 @@ did_set_string_option (
+       errmsg = e_invarg;
+     } else {
+       value_changed = STRCMP(oldval, *varp) != 0;
++
++      // Since we check the value, there is no need to set P_INSECURE,
++      // even when the value comes from a modeline.
++      *value_checked = true;
+     }
+   } else if (gvarp == &p_syn) {
+     if (!valid_filetype(*varp)) {
+       errmsg = e_invarg;
+     } else {
+       value_changed = STRCMP(oldval, *varp) != 0;
++
++      // Since we check the value, there is no need to set P_INSECURE,
++      // even when the value comes from a modeline.
++      *value_checked = true;
+     }
+   } else if (varp == &curwin->w_p_winhl) {
+     if (!parse_winhl_opt(curwin)) {
+@@ -3194,7 +3254,7 @@ did_set_string_option (
+     if (p != NULL) {
+       for (s = *varp; *s; ++s)
+         if (vim_strchr(p, *s) == NULL) {
+-          errmsg = illegal_char(errbuf, *s);
++          errmsg = illegal_char(errbuf, errbuflen, *s);
+           break;
+         }
+     }
+@@ -3258,6 +3318,11 @@ did_set_string_option (
+       // already set to this value.
+       if (!(opt_flags & OPT_MODELINE) || value_changed) {
+         static int ft_recursive = 0;
++        int secure_save = secure;
++
++        // Reset the secure flag, since the value of 'filetype' has
++        // been checked to be safe.
++        secure = 0;
+ 
+         ft_recursive++;
+         did_filetype = true;
+@@ -3270,6 +3335,7 @@ did_set_string_option (
+         if (varp != &(curbuf->b_p_ft)) {
+           varp = NULL;
+         }
++        secure = secure_save;
+       }
+     }
+     if (varp == &(curwin->w_s->b_p_spl)) {
+@@ -3287,11 +3353,13 @@ did_set_string_option (
+        * '.encoding'.
+        */
+       for (p = q; *p != NUL; ++p)
+-        if (vim_strchr((char_u *)"_.,", *p) != NULL)
++        if (!ASCII_ISALNUM(*p) && *p != '-')
+           break;
+-      vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim",
+-                   (int)(p - q), q);
+-      source_runtime(fname, DIP_ALL);
++      if (p > q) {
++        vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim",
++                     (int)(p - q), q);
++        source_runtime(fname, DIP_ALL);
++      }
+     }
+   }
+ 
+@@ -3553,7 +3621,7 @@ char_u *check_stl_option(char_u *s)
+       continue;
+     }
+     if (vim_strchr(STL_ALL, *s) == NULL) {
+-      return illegal_char(errbuf, *s);
++      return illegal_char(errbuf, sizeof(errbuf), *s);
+     }
+     if (*s == '{') {
+       s++;
+@@ -4892,19 +4960,20 @@ char *set_option_value(const char *const name, const 
long number,
+   return NULL;
+ }
+ 
+-/*
+- * Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
+- */
+-int find_key_option_len(const char_u *arg, size_t len)
++// 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.
++int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
+ {
+-  int key;
++  int key = 0;
+   int modifiers;
++  const char_u *arg = arg_arg;
+ 
+   // Don't use get_special_key_code() for t_xx, we don't want it to call
+   // add_termcap_entry().
+   if (len >= 4 && arg[0] == 't' && arg[1] == '_') {
+     key = TERMCAP2KEY(arg[2], arg[3]);
+-  } else {
++  } else if (has_lt)  {
+     arg--;  // put arg at the '<'
+     modifiers = 0;
+     key = find_special_key(&arg, len + 1, &modifiers, true, true, false);
+@@ -4915,9 +4984,9 @@ int find_key_option_len(const char_u *arg, size_t len)
+   return key;
+ }
+ 
+-static int find_key_option(const char_u *arg)
++static int find_key_option(const char_u *arg, bool has_lt)
+ {
+-  return find_key_option_len(arg, STRLEN(arg));
++  return find_key_option_len(arg, STRLEN(arg), has_lt);
+ }
+ 
+ /*
+diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
+index 6a0d0e32e..f64b07c27 100644
+--- a/src/nvim/option_defs.h
++++ b/src/nvim/option_defs.h
+@@ -503,6 +503,7 @@ EXTERN long p_mmd;              // 'maxmapdepth'
+ EXTERN long p_mmp;              // 'maxmempattern'
+ EXTERN long p_mis;              // 'menuitems'
+ EXTERN char_u   *p_msm;         // 'mkspellmem'
++EXTERN long p_mle;              // 'modelineexpr'
+ EXTERN long p_mls;              // 'modelines'
+ EXTERN char_u   *p_mouse;       // 'mouse'
+ EXTERN char_u   *p_mousem;      // 'mousemodel'
+diff --git a/src/nvim/options.lua b/src/nvim/options.lua
+index 0cc6f58c5..7ca1b4d64 100644
+--- a/src/nvim/options.lua
++++ b/src/nvim/options.lua
+@@ -8,6 +8,7 @@
+ --    defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil},
+ --    secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
+ --    pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
++--    modelineexpr=nil,
+ --    expand=nil, nodefault=nil, no_mkrc=nil, vi_def=true, vim=true,
+ --    alloced=nil,
+ --    save_pv_indir=nil,
+@@ -286,6 +287,7 @@ return {
+       deny_duplicates=true,
+       vi_def=true,
+       expand=true,
++      secure=true,
+       varname='p_cdpath',
+       defaults={if_true={vi=",,"}}
+     },
+@@ -856,6 +858,7 @@ return {
+       type='string', scope={'window'},
+       vi_def=true,
+       vim=true,
++      modelineexpr=true,
+       alloced=true,
+       redraw={'current_window'},
+       defaults={if_true={vi="0"}}
+@@ -931,6 +934,7 @@ return {
+       type='string', scope={'window'},
+       vi_def=true,
+       vim=true,
++      modelineexpr=true,
+       alloced=true,
+       redraw={'current_window'},
+       defaults={if_true={vi="foldtext()"}}
+@@ -940,6 +944,7 @@ return {
+       type='string', scope={'buffer'},
+       vi_def=true,
+       vim=true,
++      modelineexpr=true,
+       alloced=true,
+       varname='p_fex',
+       defaults={if_true={vi=""}}
+@@ -1053,6 +1058,7 @@ return {
+       full_name='guitablabel', abbreviation='gtl',
+       type='string', scope={'global'},
+       vi_def=true,
++      modelineexpr=true,
+       redraw={'current_window'},
+       enable_if=false,
+     },
+@@ -1143,6 +1149,7 @@ return {
+       full_name='iconstring',
+       type='string', scope={'global'},
+       vi_def=true,
++      modelineexpr=true,
+       varname='p_iconstring',
+       defaults={if_true={vi=""}}
+     },
+@@ -1209,6 +1216,7 @@ return {
+       full_name='includeexpr', abbreviation='inex',
+       type='string', scope={'buffer'},
+       vi_def=true,
++      modelineexpr=true,
+       alloced=true,
+       varname='p_inex',
+       defaults={if_true={vi=""}}
+@@ -1225,6 +1233,7 @@ return {
+       type='string', scope={'buffer'},
+       vi_def=true,
+       vim=true,
++      modelineexpr=true,
+       alloced=true,
+       varname='p_inde',
+       defaults={if_true={vi=""}}
+@@ -1538,6 +1547,14 @@ return {
+       varname='p_ml',
+       defaults={if_true={vi=false, vim=true}}
+     },
++    {
++      full_name='modelineexpr', abbreviation='mle',
++      type='bool', scope={'global'},
++      vi_def=true,
++      secure=true,
++      varname='p_mle',
++      defaults={if_true={vi=false}}
++    },
+     {
+       full_name='modelines', abbreviation='mls',
+       type='number', scope={'global'},
+@@ -1898,6 +1915,7 @@ return {
+       type='string', scope={'global'},
+       vi_def=true,
+       alloced=true,
++      modelineexpr=true,
+       redraw={'statuslines'},
+       varname='p_ruf',
+       defaults={if_true={vi=""}}
+@@ -2293,6 +2311,7 @@ return {
+       type='string', scope={'global', 'window'},
+       vi_def=true,
+       alloced=true,
++      modelineexpr=true,
+       redraw={'statuslines'},
+       varname='p_stl',
+       defaults={if_true={vi=""}}
+@@ -2352,6 +2371,7 @@ return {
+       full_name='tabline', abbreviation='tal',
+       type='string', scope={'global'},
+       vi_def=true,
++      modelineexpr=true,
+       redraw={'all_windows'},
+       varname='p_tal',
+       defaults={if_true={vi=""}}
+@@ -2511,6 +2531,7 @@ return {
+       full_name='titlestring',
+       type='string', scope={'global'},
+       vi_def=true,
++      modelineexpr=true,
+       varname='p_titlestring',
+       defaults={if_true={vi=""}}
+     },
+diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in
+index 435e62765..eb17ace2f 100644
+--- a/src/nvim/testdir/test49.in
++++ b/src/nvim/testdir/test49.in
+@@ -4,7 +4,7 @@ If after adding a new test, the test output doesn't appear 
properly in
+ test49.failed, try to add one or more "G"s at the line ending in "test.out"
+ 
+ STARTTEST
+-:se nomore
++:se nomore modelineexpr
+ :lang mess C
+ :so test49.vim
+ :" Go back to this file and append the results from register r.
+diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
+index 0602ff6a4..9d81d2162 100644
+--- a/src/nvim/testdir/test_alot.vim
++++ b/src/nvim/testdir/test_alot.vim
+@@ -28,6 +28,7 @@ source test_lambda.vim
+ source test_mapping.vim
+ source test_menu.vim
+ source test_messages.vim
++source test_modeline.vim
+ source test_move.vim
+ source test_partial.vim
+ source test_popup.vim
+diff --git a/src/nvim/testdir/test_autocmd.vim 
b/src/nvim/testdir/test_autocmd.vim
+index 253d6750e..12b6a38ef 100644
+--- a/src/nvim/testdir/test_autocmd.vim
++++ b/src/nvim/testdir/test_autocmd.vim
+@@ -652,6 +652,29 @@ func Test_OptionSet_diffmode_close()
+   "delfunc! AutoCommandOptionSet
+ endfunc
+ 
++func Test_OptionSet_modeline()
++  throw 'skipped: Nvim does not support test_override()'
++  call test_override('starting', 1)
++  au! OptionSet
++  augroup set_tabstop
++    au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler 
called'", "")})
++  augroup END
++  call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline')
++  set modeline
++  let v:errmsg = ''
++  call assert_fails('split XoptionsetModeline', 'E12:')
++  call assert_equal(7, &ts)
++  call assert_equal('', v:errmsg)
++
++  augroup set_tabstop
++    au!
++  augroup END
++  bwipe!
++  set ts&
++  call delete('XoptionsetModeline')
++  call test_override('starting', 0)
++endfunc
++
+ " Test for Bufleave autocommand that deletes the buffer we are about to edit.
+ func Test_BufleaveWithDelete()
+   new | edit Xfile1
+diff --git a/src/nvim/testdir/test_modeline.vim 
b/src/nvim/testdir/test_modeline.vim
+new file mode 100644
+index 000000000..1e196e07f
+--- /dev/null
++++ b/src/nvim/testdir/test_modeline.vim
+@@ -0,0 +1,173 @@
++" Tests for parsing the modeline.
++
++func Test_modeline_invalid()
++  " This was reading allocated memory in the past.
++  call writefile(['vi:0', 'nothing'], 'Xmodeline')
++  let modeline = &modeline
++  set modeline
++  call assert_fails('set Xmodeline', 'E518:')
++
++  let &modeline = modeline
++  bwipe!
++  call delete('Xmodeline')
++ endfunc
++
++func Test_modeline_filetype()
++  call writefile(['vim: set ft=c :', 'nothing'], 'Xmodeline_filetype')
++  let modeline = &modeline
++  set modeline
++  filetype plugin on
++  split Xmodeline_filetype
++  call assert_equal("c", &filetype)
++  call assert_equal(1, b:did_ftplugin)
++  call assert_equal("ccomplete#Complete", &ofu)
++
++  bwipe!
++  call delete('Xmodeline_filetype')
++  let &modeline = modeline
++  filetype plugin off
++endfunc
++
++func Test_modeline_syntax()
++  call writefile(['vim: set syn=c :', 'nothing'], 'Xmodeline_syntax')
++  let modeline = &modeline
++  set modeline
++  syntax enable
++  split Xmodeline_syntax
++  call assert_equal("c", &syntax)
++  call assert_equal("c", b:current_syntax)
++
++  bwipe!
++  call delete('Xmodeline_syntax')
++  let &modeline = modeline
++  syntax off
++endfunc
++
++func Test_modeline_keymap()
++  if !has('keymap')
++    return
++  endif
++  call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap')
++  let modeline = &modeline
++  set modeline
++  split Xmodeline_keymap
++  call assert_equal("greek", &keymap)
++  call assert_match('greek\|grk', b:keymap_name)
++
++  bwipe!
++  call delete('Xmodeline_keymap')
++  let &modeline = modeline
++  set keymap= iminsert=0 imsearch=-1
++endfunc
++
++func s:modeline_fails(what, text, error)
++  if !exists('+' . a:what)
++    return
++  endif
++  let fname = "Xmodeline_fails_" . a:what
++  call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname)
++  let modeline = &modeline
++  set modeline
++  filetype plugin on
++  syntax enable
++  call assert_fails('split ' . fname, a:error)
++  call assert_equal("", &filetype)
++  call assert_equal("", &syntax)
++
++  bwipe!
++  call delete(fname)
++  let &modeline = modeline
++  filetype plugin off
++  syntax off
++endfunc
++
++func Test_modeline_filetype_fails()
++  call s:modeline_fails('filetype', 'ft=evil$CMD', 'E474:')
++endfunc
++
++func Test_modeline_syntax_fails()
++  call s:modeline_fails('syntax', 'syn=evil$CMD', 'E474:')
++endfunc
++
++func Test_modeline_keymap_fails()
++  call s:modeline_fails('keymap', 'keymap=evil$CMD', 'E474:')
++endfunc
++
++func Test_modeline_fails_always()
++  call s:modeline_fails('backupdir', 'backupdir=Something()', 'E520:')
++  call s:modeline_fails('cdpath', 'cdpath=Something()', 'E520:')
++  call s:modeline_fails('charconvert', 'charconvert=Something()', 'E520:')
++  call s:modeline_fails('completefunc', 'completefunc=Something()', 'E520:')
++  call s:modeline_fails('cscopeprg', 'cscopeprg=Something()', 'E520:')
++  call s:modeline_fails('diffexpr', 'diffexpr=Something()', 'E520:')
++  call s:modeline_fails('directory', 'directory=Something()', 'E520:')
++  call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:')
++  call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:')
++  call s:modeline_fails('exrc', 'exrc=Something()', 'E520:')
++  call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:')
++  call s:modeline_fails('fsync', 'fsync=Something()', 'E520:')
++  call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:')
++  call s:modeline_fails('helpfile', 'helpfile=Something()', 'E520:')
++  call s:modeline_fails('imactivatefunc', 'imactivatefunc=Something()', 
'E520:')
++  call s:modeline_fails('imstatusfunc', 'imstatusfunc=Something()', 'E520:')
++  call s:modeline_fails('imstyle', 'imstyle=Something()', 'E520:')
++  call s:modeline_fails('keywordprg', 'keywordprg=Something()', 'E520:')
++  call s:modeline_fails('langmap', 'langmap=Something()', 'E520:')
++  call s:modeline_fails('luadll', 'luadll=Something()', 'E520:')
++  call s:modeline_fails('makeef', 'makeef=Something()', 'E520:')
++  call s:modeline_fails('makeprg', 'makeprg=Something()', 'E520:')
++  call s:modeline_fails('mkspellmem', 'mkspellmem=Something()', 'E520:')
++  call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:')
++  call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:')
++  call s:modeline_fails('modelineexpr', 'modelineexpr=Something()', 'E520:')
++  call s:modeline_fails('omnifunc', 'omnifunc=Something()', 'E520:')
++  call s:modeline_fails('operatorfunc', 'operatorfunc=Something()', 'E520:')
++  call s:modeline_fails('perldll', 'perldll=Something()', 'E520:')
++  call s:modeline_fails('printdevice', 'printdevice=Something()', 'E520:')
++  call s:modeline_fails('patchexpr', 'patchexpr=Something()', 'E520:')
++  call s:modeline_fails('printexpr', 'printexpr=Something()', 'E520:')
++  call s:modeline_fails('pythondll', 'pythondll=Something()', 'E520:')
++  call s:modeline_fails('pythonhome', 'pythonhome=Something()', 'E520:')
++  call s:modeline_fails('pythonthreedll', 'pythonthreedll=Something()', 
'E520:')
++  call s:modeline_fails('pythonthreehome', 'pythonthreehome=Something()', 
'E520:')
++  call s:modeline_fails('pyxversion', 'pyxversion=Something()', 'E520:')
++  call s:modeline_fails('rubydll', 'rubydll=Something()', 'E520:')
++  call s:modeline_fails('runtimepath', 'runtimepath=Something()', 'E520:')
++  call s:modeline_fails('secure', 'secure=Something()', 'E520:')
++  call s:modeline_fails('shell', 'shell=Something()', 'E520:')
++  call s:modeline_fails('shellcmdflag', 'shellcmdflag=Something()', 'E520:')
++  call s:modeline_fails('shellpipe', 'shellpipe=Something()', 'E520:')
++  call s:modeline_fails('shellquote', 'shellquote=Something()', 'E520:')
++  call s:modeline_fails('shellredir', 'shellredir=Something()', 'E520:')
++  call s:modeline_fails('shellxquote', 'shellxquote=Something()', 'E520:')
++  call s:modeline_fails('spellfile', 'spellfile=Something()', 'E520:')
++  call s:modeline_fails('spellsuggest', 'spellsuggest=Something()', 'E520:')
++  call s:modeline_fails('tcldll', 'tcldll=Something()', 'E520:')
++  call s:modeline_fails('titleold', 'titleold=Something()', 'E520:')
++  call s:modeline_fails('viewdir', 'viewdir=Something()', 'E520:')
++  call s:modeline_fails('viminfo', 'viminfo=Something()', 'E520:')
++  call s:modeline_fails('viminfofile', 'viminfofile=Something()', 'E520:')
++  call s:modeline_fails('winptydll', 'winptydll=Something()', 'E520:')
++  call s:modeline_fails('undodir', 'undodir=Something()', 'E520:')
++  " only check a few terminal options
++  " Skip these since nvim doesn't support termcodes as options
++  "call s:modeline_fails('t_AB', 't_AB=Something()', 'E520:')
++  "call s:modeline_fails('t_ce', 't_ce=Something()', 'E520:')
++  "call s:modeline_fails('t_sr', 't_sr=Something()', 'E520:')
++  "call s:modeline_fails('t_8b', 't_8b=Something()', 'E520:')
++endfunc
++
++func Test_modeline_fails_modelineexpr()
++  call s:modeline_fails('balloonexpr', 'balloonexpr=Something()', 'E992:')
++  call s:modeline_fails('foldexpr', 'foldexpr=Something()', 'E992:')
++  call s:modeline_fails('foldtext', 'foldtext=Something()', 'E992:')
++  call s:modeline_fails('formatexpr', 'formatexpr=Something()', 'E992:')
++  call s:modeline_fails('guitablabel', 'guitablabel=Something()', 'E992:')
++  call s:modeline_fails('iconstring', 'iconstring=Something()', 'E992:')
++  call s:modeline_fails('includeexpr', 'includeexpr=Something()', 'E992:')
++  call s:modeline_fails('indentexpr', 'indentexpr=Something()', 'E992:')
++  call s:modeline_fails('rulerformat', 'rulerformat=Something()', 'E992:')
++  call s:modeline_fails('statusline', 'statusline=Something()', 'E992:')
++  call s:modeline_fails('tabline', 'tabline=Something()', 'E992:')
++  call s:modeline_fails('titlestring', 'titlestring=Something()', 'E992:')
++endfunc
diff -Nru 
neovim-0.3.4/debian/patches/0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 
neovim-0.3.4/debian/patches/0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
--- 
neovim-0.3.4/debian/patches/0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 2019-06-05 21:38:14.000000000 -0400
+++ 
neovim-0.3.4/debian/patches/0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-From 46112054bf3c6d00c53cf8a904e0687b508a4f0a Mon Sep 17 00:00:00 2001
-From: "Justin M. Keyes" <justi...@gmail.com>
-Date: Wed, 29 May 2019 00:33:22 +0200
-Subject: [PATCH] vim-patch:8.1.1365: :source should check sandbox #10082
-
-Problem:    Source command doesn't check for the sandbox. (Armin Razmjou)
-Solution:   Check for the sandbox when sourcing a file.
-https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040
-
-(cherry picked from commit 4553fc5e6cb6c8c43f57c173d01b31a61e51d13f)
-
-Signed-off-by: James McCoy <james...@debian.org>
-Closes: CVE-2019-12735
-Closes: #930024
----
- src/nvim/getchar.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
-index 94702a9a3..243e6afce 100644
---- a/src/nvim/getchar.c
-+++ b/src/nvim/getchar.c
-@@ -1244,6 +1244,13 @@ openscript (
-     EMSG(_(e_nesting));
-     return;
-   }
-+
-+  // Disallow sourcing a file in the sandbox, the commands would be executed
-+  // later, possibly outside of the sandbox.
-+  if (check_secure()) {
-+    return;
-+  }
-+
-   if (ignore_script)
-     /* Not reading from script, also don't open one.  Warning message? */
-     return;
diff -Nru 
neovim-0.3.4/debian/patches/0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 
neovim-0.3.4/debian/patches/0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
--- 
neovim-0.3.4/debian/patches/0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
 2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,36 @@
+From 0deb5bd4710ca912420bd796e74f6a7175d7753f Mon Sep 17 00:00:00 2001
+From: "Justin M. Keyes" <justi...@gmail.com>
+Date: Wed, 29 May 2019 00:33:22 +0200
+Subject: [PATCH 2/7] vim-patch:8.1.1365: :source should check sandbox #10082
+
+Problem:    Source command doesn't check for the sandbox. (Armin Razmjou)
+Solution:   Check for the sandbox when sourcing a file.
+https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040
+
+(cherry picked from commit 4553fc5e6cb6c8c43f57c173d01b31a61e51d13f)
+
+Signed-off-by: James McCoy <james...@debian.org>
+Closes: CVE-2019-12735
+Closes: #930024
+---
+ src/nvim/getchar.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
+index 94702a9a3..243e6afce 100644
+--- a/src/nvim/getchar.c
++++ b/src/nvim/getchar.c
+@@ -1244,6 +1244,13 @@ openscript (
+     EMSG(_(e_nesting));
+     return;
+   }
++
++  // Disallow sourcing a file in the sandbox, the commands would be executed
++  // later, possibly outside of the sandbox.
++  if (check_secure()) {
++    return;
++  }
++
+   if (ignore_script)
+     /* Not reading from script, also don't open one.  Warning message? */
+     return;
diff -Nru 
neovim-0.3.4/debian/patches/0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch
 
neovim-0.3.4/debian/patches/0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch
--- 
neovim-0.3.4/debian/patches/0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch
 1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch
 2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,104 @@
+From ee6325436e32803a8b2e4678ff334c7b9423ef7e Mon Sep 17 00:00:00 2001
+From: Jan Edmund Lazo <jan.l...@mail.utoronto.ca>
+Date: Sat, 23 Mar 2019 00:58:00 -0400
+Subject: [PATCH 3/7] vim-patch:8.1.0177: defining function in sandbox is
+ inconsistent
+
+Problem:    Defining function in sandbox is inconsistent, cannot use :function
+            but can define a lambda.
+Solution:   Allow defining a function in the sandbox, but also use the sandbox
+            when executing it. (closes vim/vim#3182)
+https://github.com/vim/vim/commit/93343725b5fa1cf580a24302455980faacae8ee2
+
+(cherry picked from commit c202e4a86856594a6602a795314a081c497c2df5)
+
+Signed-off-by: James McCoy <james...@debian.org>
+---
+ src/nvim/eval.c      | 19 ++++++++++++++++++-
+ src/nvim/ex_cmds.lua |  2 +-
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/src/nvim/eval.c b/src/nvim/eval.c
+index 5191328b5..9163673a3 100644
+--- a/src/nvim/eval.c
++++ b/src/nvim/eval.c
+@@ -241,13 +241,14 @@ typedef enum {
+                                   ///< the value (prevents error message).
+ } GetLvalFlags;
+ 
+-// function flags
++// flags used in uf_flags
+ #define FC_ABORT    0x01          // abort function on error
+ #define FC_RANGE    0x02          // function accepts range
+ #define FC_DICT     0x04          // Dict function, uses "self"
+ #define FC_CLOSURE  0x08          // closure, uses outer scope variables
+ #define FC_DELETED  0x10          // :delfunction used while uf_refcount > 0
+ #define FC_REMOVED  0x20          // function redefined while uf_refcount > 0
++#define FC_SANDBOX  0x40          // function defined in the sandbox
+ 
+ // The names of packages that once were loaded are remembered.
+ static garray_T ga_loaded = { 0, 0, sizeof(char_u *), 4, NULL };
+@@ -5853,6 +5854,9 @@ static int get_lambda_tv(char_u **arg, typval_T *rettv, 
bool evaluate)
+     if (prof_def_func()) {
+       func_do_profile(fp);
+     }
++    if (sandbox) {
++      flags |= FC_SANDBOX;
++    }
+     fp->uf_varargs = true;
+     fp->uf_flags = flags;
+     fp->uf_calls = 0;
+@@ -20315,6 +20319,9 @@ void ex_function(exarg_T *eap)
+   if (prof_def_func())
+     func_do_profile(fp);
+   fp->uf_varargs = varargs;
++  if (sandbox) {
++    flags |= FC_SANDBOX;
++  }
+   fp->uf_flags = flags;
+   fp->uf_calls = 0;
+   fp->uf_script_ID = current_SID;
+@@ -21305,6 +21312,7 @@ void call_user_func(ufunc_T *fp, int argcount, 
typval_T *argvars,
+   char_u      *save_sourcing_name;
+   linenr_T save_sourcing_lnum;
+   scid_T save_current_SID;
++  bool using_sandbox = false;
+   funccall_T  *fc;
+   int save_did_emsg;
+   static int depth = 0;
+@@ -21462,6 +21470,12 @@ void call_user_func(ufunc_T *fp, int argcount, 
typval_T *argvars,
+   save_sourcing_name = sourcing_name;
+   save_sourcing_lnum = sourcing_lnum;
+   sourcing_lnum = 1;
++
++  if (fp->uf_flags & FC_SANDBOX) {
++    using_sandbox = true;
++    sandbox++;
++  }
++
+   // need space for new sourcing_name:
+   // * save_sourcing_name
+   // * "["number"].." or "function "
+@@ -21622,6 +21636,9 @@ void call_user_func(ufunc_T *fp, int argcount, 
typval_T *argvars,
+   if (do_profiling_yes) {
+     script_prof_restore(&wait_start);
+   }
++  if (using_sandbox) {
++    sandbox--;
++  }
+ 
+   if (p_verbose >= 12 && sourcing_name != NULL) {
+     ++no_wait_return;
+diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
+index 79ca5363e..fae21d8c9 100644
+--- a/src/nvim/ex_cmds.lua
++++ b/src/nvim/ex_cmds.lua
+@@ -1004,7 +1004,7 @@ return {
+   },
+   {
+     command='function',
+-    flags=bit.bor(EXTRA, BANG, CMDWIN),
++    flags=bit.bor(EXTRA, BANG, SBOXOK, CMDWIN),
+     addr_type=ADDR_LINES,
+     func='ex_function',
+   },
diff -Nru 
neovim-0.3.4/debian/patches/0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch
 
neovim-0.3.4/debian/patches/0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch
--- 
neovim-0.3.4/debian/patches/0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch
 1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch
 2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,41 @@
+From 5be949ce2df74446f33ea2949620234b41c046b0 Mon Sep 17 00:00:00 2001
+From: Jan Edmund Lazo <jan.l...@mail.utoronto.ca>
+Date: Sat, 23 Mar 2019 01:26:07 -0400
+Subject: [PATCH 4/7] vim-patch:8.1.0189: function defined in sandbox not
+ tested
+
+Problem:    Function defined in sandbox not tested.
+Solution:   Add a text.
+https://github.com/vim/vim/commit/d90a144eda047816acffc7a8f297b43a7120710e
+
+(cherry picked from commit f514b7fbbc75b4464af5abe44d5f859a0d904495)
+
+Signed-off-by: James McCoy <james...@debian.org>
+---
+ src/nvim/testdir/test_functions.vim | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/nvim/testdir/test_functions.vim 
b/src/nvim/testdir/test_functions.vim
+index 7dc9f31ce..292f69d70 100644
+--- a/src/nvim/testdir/test_functions.vim
++++ b/src/nvim/testdir/test_functions.vim
+@@ -1037,3 +1037,19 @@ func Test_func_range_with_edit()
+   call delete('Xfuncrange2')
+   bwipe!
+ endfunc
++
++sandbox function Fsandbox()
++  normal ix
++endfunc
++
++func Test_func_sandbox()
++  sandbox let F = {-> 'hello'}
++  call assert_equal('hello', F())
++
++  sandbox let F = {-> execute("normal ix\<Esc>")}
++  call assert_fails('call F()', 'E48:')
++  unlet F
++
++  call assert_fails('call Fsandbox()', 'E48:')
++  delfunc Fsandbox
++endfunc
diff -Nru 
neovim-0.3.4/debian/patches/0005-vim-patch-8.1.0206-duplicate-test-function-name.patch
 
neovim-0.3.4/debian/patches/0005-vim-patch-8.1.0206-duplicate-test-function-name.patch
--- 
neovim-0.3.4/debian/patches/0005-vim-patch-8.1.0206-duplicate-test-function-name.patch
      1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0005-vim-patch-8.1.0206-duplicate-test-function-name.patch
      2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,35 @@
+From 86093f2847efb7e0579247b7ff850e4cafe71912 Mon Sep 17 00:00:00 2001
+From: Jan Edmund Lazo <jan.l...@mail.utoronto.ca>
+Date: Sat, 25 May 2019 14:47:17 -0400
+Subject: [PATCH 5/7] vim-patch:8.1.0206: duplicate test function name
+
+Problem:    Duplicate test function name.
+Solution:   Rename both functions.
+https://github.com/vim/vim/commit/cd96eef3a869557bd3d2d4497861d87cb525db06
+
+(cherry picked from commit 6683cb60b805fa305a069cf7873be8b605d78a3d)
+
+Signed-off-by: James McCoy <james...@debian.org>
+---
+ src/nvim/testdir/test_glob2regpat.vim | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/nvim/testdir/test_glob2regpat.vim 
b/src/nvim/testdir/test_glob2regpat.vim
+index fdf17946b..e6e41f13e 100644
+--- a/src/nvim/testdir/test_glob2regpat.vim
++++ b/src/nvim/testdir/test_glob2regpat.vim
+@@ -1,12 +1,12 @@
+ " Test glob2regpat()
+ 
+-func Test_invalid()
++func Test_glob2regpat_invalid()
+   call assert_fails('call glob2regpat(1.33)', 'E806:')
+   call assert_fails('call glob2regpat("}")', 'E219:')
+   call assert_fails('call glob2regpat("{")', 'E220:')
+ endfunc
+ 
+-func Test_valid()
++func Test_glob2regpat_valid()
+   call assert_equal('^foo\.', glob2regpat('foo.*'))
+   call assert_equal('^foo.$', glob2regpat('foo?'))
+   call assert_equal('\.vim$', glob2regpat('*.vim'))
diff -Nru 
neovim-0.3.4/debian/patches/0006-vim-patch-8.1.1382-error-when-editing-test-file.patch
 
neovim-0.3.4/debian/patches/0006-vim-patch-8.1.1382-error-when-editing-test-file.patch
--- 
neovim-0.3.4/debian/patches/0006-vim-patch-8.1.1382-error-when-editing-test-file.patch
      1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0006-vim-patch-8.1.1382-error-when-editing-test-file.patch
      2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,59 @@
+From e45938b8c7465d854b3d4feeff6acfc71835078f Mon Sep 17 00:00:00 2001
+From: James McCoy <james...@jamessan.com>
+Date: Sat, 22 Jun 2019 22:09:32 -0400
+Subject: [PATCH 6/7] vim-patch:8.1.1382: error when editing test file
+
+Problem:    Error when editing test file.
+Solution:   Remove part of modeline.
+https://github.com/vim/vim/commit/3020a87cb121123abf1e9a1eca0eddac241fc481
+
+(cherry picked from commit 13f3a21226fdd31c42ba927ff12ac6c34c940311)
+
+Signed-off-by: James McCoy <james...@debian.org>
+---
+ src/nvim/testdir/test49.in          | 2 +-
+ src/nvim/testdir/test49.vim         | 3 +--
+ src/nvim/testdir/test_vimscript.vim | 1 -
+ 3 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in
+index eb17ace2f..435e62765 100644
+--- a/src/nvim/testdir/test49.in
++++ b/src/nvim/testdir/test49.in
+@@ -4,7 +4,7 @@ If after adding a new test, the test output doesn't appear 
properly in
+ test49.failed, try to add one or more "G"s at the line ending in "test.out"
+ 
+ STARTTEST
+-:se nomore modelineexpr
++:se nomore
+ :lang mess C
+ :so test49.vim
+ :" Go back to this file and append the results from register r.
+diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
+index 467abcd9b..837e55ebc 100644
+--- a/src/nvim/testdir/test49.vim
++++ b/src/nvim/testdir/test49.vim
+@@ -1,6 +1,6 @@
+ " Vim script language tests
+ " Author:     Servatius Brandt <servatius.bra...@fujitsu-siemens.com>
+-" Last Change:        2016 Feb 07
++" Last Change:        2019 May 24
+ 
+ 
"-------------------------------------------------------------------------------
+ " Test environment                                                        {{{1
+@@ -9005,5 +9005,4 @@ Xcheck 50443995
+ 
"-------------------------------------------------------------------------------
+ " Modelines                                                               {{{1
+ " vim: ts=8 sw=4 tw=80 fdm=marker
+-" vim: fdt=substitute(substitute(foldtext(),\ 
'\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ 
\\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ 
'\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
+ 
"-------------------------------------------------------------------------------
+diff --git a/src/nvim/testdir/test_vimscript.vim 
b/src/nvim/testdir/test_vimscript.vim
+index 5b16f6d20..c856fd720 100644
+--- a/src/nvim/testdir/test_vimscript.vim
++++ b/src/nvim/testdir/test_vimscript.vim
+@@ -1297,5 +1297,4 @@ endfunc
+ 
"-------------------------------------------------------------------------------
+ " Modelines                                                               {{{1
+ " vim: ts=8 sw=4 tw=80 fdm=marker
+-" vim: fdt=substitute(substitute(foldtext(),\ 
'\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ 
\\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ 
'\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
+ 
"-------------------------------------------------------------------------------
diff -Nru 
neovim-0.3.4/debian/patches/0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch
 
neovim-0.3.4/debian/patches/0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch
--- 
neovim-0.3.4/debian/patches/0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch
 1969-12-31 19:00:00.000000000 -0500
+++ 
neovim-0.3.4/debian/patches/0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch
 2019-06-26 21:21:33.000000000 -0400
@@ -0,0 +1,57 @@
+From 3e2e812f17fd05687dd9ffdbd42ccf9d31ee9bc7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Linse?= <bjorn.li...@gmail.com>
+Date: Wed, 26 Jun 2019 08:11:51 +0200
+Subject: [PATCH 7/7] eval/api: don't allow the API to be called in the
+ sandbox.
+
+Identifying and maintaining a "secure" subset of the API would be too
+much busywork. So just disable the entire thing.
+
+(cherry picked from commit 413b313ad2cfd5a1ee32369b944436e14fc8bfb3)
+
+Signed-off-by: James McCoy <james...@debian.org>
+---
+ src/nvim/eval.c                             | 4 ++++
+ test/functional/eval/api_functions_spec.lua | 9 ++++++++-
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/src/nvim/eval.c b/src/nvim/eval.c
+index 9163673a3..618cd50a7 100644
+--- a/src/nvim/eval.c
++++ b/src/nvim/eval.c
+@@ -6516,6 +6516,10 @@ static void float_op_wrapper(typval_T *argvars, 
typval_T *rettv, FunPtr fptr)
+ 
+ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+ {
++  if (check_restricted() || check_secure()) {
++    return;
++  }
++
+   ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr;
+ 
+   Array args = ARRAY_DICT_INIT;
+diff --git a/test/functional/eval/api_functions_spec.lua 
b/test/functional/eval/api_functions_spec.lua
+index 6f440c7d8..951c5d685 100644
+--- a/test/functional/eval/api_functions_spec.lua
++++ b/test/functional/eval/api_functions_spec.lua
+@@ -4,7 +4,8 @@ local lfs = require('lfs')
+ local neq, eq, command = helpers.neq, helpers.eq, helpers.command
+ local clear, curbufmeths = helpers.clear, helpers.curbufmeths
+ local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval
+-local insert = helpers.insert
++local insert, meth_pcall = helpers.insert, helpers.meth_pcall
++local meths = helpers.meths
+ 
+ describe('api functions', function()
+   before_each(clear)
+@@ -145,4 +146,10 @@ describe('api functions', function()
+     ]])
+     screen:detach()
+   end)
++
++  it('cannot be called from sandbox', function()
++    eq({false, 'Vim(call):E48: Not allowed in sandbox'},
++       meth_pcall(command, "sandbox call nvim_input('ievil')"))
++    eq({''}, meths.buf_get_lines(0, 0, -1, true))
++  end)
+ end)
diff -Nru neovim-0.3.4/debian/patches/series neovim-0.3.4/debian/patches/series
--- neovim-0.3.4/debian/patches/series  2019-06-05 21:38:14.000000000 -0400
+++ neovim-0.3.4/debian/patches/series  2019-06-26 21:21:33.000000000 -0400
@@ -1,2 +1,8 @@
 # exported from git by git-debcherry
-0001-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
+0001-debcherry-fixup-patch.patch
+0002-vim-patch-8.1.1365-source-should-check-sandbox-10082.patch
+0003-vim-patch-8.1.0177-defining-function-in-sandbox-is-i.patch
+0004-vim-patch-8.1.0189-function-defined-in-sandbox-not-t.patch
+0005-vim-patch-8.1.0206-duplicate-test-function-name.patch
+0006-vim-patch-8.1.1382-error-when-editing-test-file.patch
+0007-eval-api-don-t-allow-the-API-to-be-called-in-the-san.patch

Reply via email to