patch 9.1.1415: potential use-after free when there is an error in 'tabpanel'

Problem:  potential use-after free when there is an error in 'tabpanel'
          option (@char101, after v9.1.1391)
Solution: check if p_tpl has been set to null before accessing it again.

While at it slightly change starts_with_percent_and_bang() and use the
existing opt_name and opt_scope variables.

fixes: #17364
closes: #17388

Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/tabpanel.c b/src/tabpanel.c
index bb7a874..599e434 100644
--- a/src/tabpanel.c
+++ b/src/tabpanel.c
@@ -530,8 +530,8 @@
 	if (did_emsg > did_emsg_before)
 	{
 	    usefmt = NULL;
-	    set_string_option_direct((char_u *)"tabpanel", -1, (char_u *)"",
-		    OPT_FREE | OPT_GLOBAL, SID_ERROR);
+	    set_string_option_direct(opt_name, -1, (char_u *)"",
+		    OPT_FREE | opt_scope, SID_ERROR);
 	}
     }
 #endif
@@ -641,6 +641,12 @@
 		args.prow = &row;
 		args.pcol = &col;
 		draw_tabpanel_userdefined(tplmode, &args);
+		// p_tpl could have been freed in build_stl_str_hl()
+		if (p_tpl == NULL || *p_tpl == NUL)
+		{
+		    usefmt = NULL;
+		    break;
+		}
 
 		p += i;
 		i = 0;
diff --git a/src/testdir/test_tabpanel.vim b/src/testdir/test_tabpanel.vim
index 46ebe3b..e0a6a8c 100644
--- a/src/testdir/test_tabpanel.vim
+++ b/src/testdir/test_tabpanel.vim
@@ -529,6 +529,14 @@
   catch /^Vim\%((\a\+)\)\=:E117:/
   endtry
   call assert_true(empty(&tabpanel))
+
+  try
+    set tabpanel=%{my#util#TabPanelHighlight}%t
+    redraw!
+  catch /^Vim\%((\a\+)\)\=:E121:/
+  endtry
+  call assert_true(empty(&tabpanel))
+
   set tabpanel&vim
   set showtabpanel&vim
 endfunc
diff --git a/src/version.c b/src/version.c
index 5366f3f..a788db1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -710,6 +710,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1415,
+/**/
     1414,
 /**/
     1413,