patch 8.1.0544: setting 'filetype' in a modeline causes an error

Problem:    Setting 'filetype' in a modeline causes an error (Hirohito
            Higashi).
Solution:   Don't add the P_INSECURE flag when setting 'filetype' from a
            modeline.  Also for 'syntax'.
diff --git a/src/option.c b/src/option.c
index fdb99ad..192d292 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3284,7 +3284,7 @@
 static void set_options_default(int opt_flags);
 static void set_string_default_esc(char *name, char_u *val, int escape);
 static char_u *term_bg_default(void);
-static void did_set_option(int opt_idx, int opt_flags, int new_value);
+static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked);
 static char_u *option_expand(int opt_idx, char_u *val);
 static void didset_options(void);
 static void didset_options2(void);
@@ -3295,7 +3295,7 @@
 # define insecure_flag(opt_idx, opt_flags) (&options[opt_idx].flags)
 #endif
 static void set_string_option_global(int opt_idx, char_u **varp);
-static char_u *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags);
+static char_u *did_set_string_option(int opt_idx, char_u **varp, int new_value_alloced, char_u *oldval, char_u *errbuf, int opt_flags, int *value_checked);
 static char_u *set_chars_option(char_u **varp);
 #ifdef FEAT_CLIPBOARD
 static char_u *check_clipboard_option(void);
@@ -4706,6 +4706,7 @@
 	    else
 	    {
 		int value_is_replaced = !prepending && !adding && !removing;
+		int value_checked = FALSE;
 
 		if (flags & P_BOOL)		    /* boolean */
 		{
@@ -5236,7 +5237,8 @@
 			    // 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);
+				    new_value_alloced, oldval, errbuf,
+				    opt_flags, &value_checked);
 
 			    if (did_inc_secure)
 				--secure;
@@ -5280,7 +5282,8 @@
 		}
 
 		if (opt_idx >= 0)
-		    did_set_option(opt_idx, opt_flags, value_is_replaced);
+		    did_set_option(
+			 opt_idx, opt_flags, value_is_replaced, value_checked);
 	    }
 
 skip:
@@ -5348,8 +5351,10 @@
     static void
 did_set_option(
     int	    opt_idx,
-    int	    opt_flags,	    /* possibly with OPT_MODELINE */
-    int	    new_value)	    /* value was replaced completely */
+    int	    opt_flags,	    // possibly with OPT_MODELINE
+    int	    new_value,	    // value was replaced completely
+    int	    value_checked)  // value was checked to be safe, no need to set the
+			    // P_INSECURE flag.
 {
     long_u	*p;
 
@@ -5359,11 +5364,11 @@
      * set the P_INSECURE flag.  Otherwise, if a new value is stored reset the
      * flag. */
     p = insecure_flag(opt_idx, opt_flags);
-    if (secure
+    if (!value_checked && (secure
 #ifdef HAVE_SANDBOX
 	    || sandbox != 0
 #endif
-	    || (opt_flags & OPT_MODELINE))
+	    || (opt_flags & OPT_MODELINE)))
 	*p = *p | P_INSECURE;
     else if (new_value)
 	*p = *p & ~P_INSECURE;
@@ -6036,6 +6041,7 @@
     char_u	*saved_newval = NULL;
 #endif
     char_u	*r = NULL;
+    int		value_checked = FALSE;
 
     if (options[opt_idx].var == NULL)	/* don't set hidden option */
 	return NULL;
@@ -6063,8 +6069,8 @@
 	}
 #endif
 	if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
-							   opt_flags)) == NULL)
-	    did_set_option(opt_idx, opt_flags, TRUE);
+					   opt_flags, &value_checked)) == NULL)
+	    did_set_option(opt_idx, opt_flags, TRUE, value_checked);
 
 #if defined(FEAT_EVAL)
 	/* call autocommand after handling side effects */
@@ -6099,12 +6105,14 @@
  */
     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 */
+    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
+    int		*value_checked)		// value was checked to be save, no
+					// need to set P_INSECURE
 {
     char_u	*errmsg = NULL;
     char_u	*s, *p;
@@ -6134,10 +6142,9 @@
 	errmsg = e_secure;
     }
 
-    /* Check for a "normal" directory or file name in some options.  Disallow a
-     * path separator (slash and/or backslash), wildcards and characters that
-     * are often illegal in a file name. Be more permissive if "secure" is off.
-     */
+    // Check for a "normal" directory or file name in some options.  Disallow a
+    // path separator (slash and/or backslash), wildcards and characters that
+    // are often illegal in a file name. Be more permissive if "secure" is off.
     else if (((options[opt_idx].flags & P_NFNAME)
 		    && vim_strpbrk(*varp, (char_u *)(secure
 			    ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
@@ -6524,9 +6531,23 @@
 	if (!valid_filetype(*varp))
 	    errmsg = e_invarg;
 	else
-	    /* load or unload key mapping tables */
+	{
+	    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)
 	{
 	    if (*curbuf->b_p_keymap != NUL)
@@ -7523,7 +7544,13 @@
 	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;
+	}
     }
 
 #ifdef FEAT_SYN_HL
@@ -7532,7 +7559,13 @@
 	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;
+	}
     }
 #endif
 
@@ -7752,7 +7785,12 @@
 	     * already set to this value. */
 	    if (!(opt_flags & OPT_MODELINE) || value_changed)
 	    {
-		static int ft_recursive = 0;
+		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;
@@ -7764,6 +7802,8 @@
 		/* Just in case the old "curbuf" is now invalid. */
 		if (varp != &(curbuf->b_p_ft))
 		    varp = NULL;
+
+		secure = secure_save;
 	    }
 	}
 #ifdef FEAT_SPELL