]> granicus.if.org Git - vim/commitdiff
patch 9.0.0221: accessing freed memory if compiling nested function fails v9.0.0221
authorBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2022 18:34:44 +0000 (19:34 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 16 Aug 2022 18:34:44 +0000 (19:34 +0100)
Problem:    Accessing freed memory if compiling nested function fails.
Solution:   Mess up the variable name so that it won't be found.

src/testdir/test_vim9_func.vim
src/version.c
src/vim9compile.c

index 5c7545784f3d6d35c06e564ef85cadb9cf76351c..fd7182d50e08218300d5e1caa8ade70d426e4a11 100644 (file)
@@ -911,6 +911,18 @@ def Test_nested_function()
   v9.CheckScriptFailure(lines, 'E1173: Text found after enddef: burp', 3)
 enddef
 
+def Test_nested_function_fails()
+  var lines =<< trim END
+      def T()
+        def Func(g: string):string
+        enddef
+        Func()
+      enddef
+      silent! defcompile
+  END
+  v9.CheckScriptFailure(lines, 'E1069:')
+enddef
+
 def Test_not_nested_function()
   echo printf('%d',
       function('len')('xxx'))
index a6293e0cfa16202d7edaf87f3758bd0a56263373..03d641fd77f74b150d1177574ba9b98fa2c2d98e 100644 (file)
@@ -735,6 +735,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    221,
 /**/
     220,
 /**/
index 98fc84c58a4cbf8b2299724492db9e57d94a08c2..d1e2c87fd82c6c3c9af0b8ccb0d00e8bffcb357c 100644 (file)
@@ -830,6 +830,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
     int                r = FAIL;
     compiletype_T   compile_type;
     isn_T      *funcref_isn = NULL;
+    lvar_T     *lvar = NULL;
 
     if (eap->forceit)
     {
@@ -936,9 +937,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
     else
     {
        // Define a local variable for the function reference.
-       lvar_T  *lvar = reserve_local(cctx, func_name, name_end - name_start,
+       lvar = reserve_local(cctx, func_name, name_end - name_start,
                                                    TRUE, ufunc->uf_func_type);
-
        if (lvar == NULL)
            goto theend;
        if (generate_FUNCREF(cctx, ufunc, &funcref_isn) == FAIL)
@@ -957,6 +957,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
            && compile_def_function(ufunc, TRUE, compile_type, cctx) == FAIL)
     {
        func_ptr_unref(ufunc);
+       if (lvar != NULL)
+           // Now the local variable can't be used.
+           *lvar->lv_name = '/';  // impossible value
        goto theend;
     }