]> granicus.if.org Git - vim/commitdiff
patch 8.2.2636: memory leak when compiling inline function v8.2.2636
authorBram Moolenaar <Bram@vim.org>
Sun, 21 Mar 2021 21:12:34 +0000 (22:12 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 21 Mar 2021 21:12:34 +0000 (22:12 +0100)
Problem:    Memory leak when compiling inline function.
Solution:   Free the prefetched line.

src/eval.c
src/globals.h
src/structs.h
src/userfunc.c
src/version.c
src/vim9compile.c

index aa5f5b8243ea62aea9104b1ea4c7d4c59f296aba..6cdc10f68bfd69d0ca5b22dc7096b904f68f8377 100644 (file)
@@ -2179,8 +2179,8 @@ clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
            evalarg->eval_tofree = NULL;
        }
 
-       vim_free(evalarg->eval_tofree_lambda);
-       evalarg->eval_tofree_lambda = NULL;
+       VIM_CLEAR(evalarg->eval_tofree_cmdline);
+       VIM_CLEAR(evalarg->eval_tofree_lambda);
     }
 }
 
index cb3b4f4b76288e65754dea9f7a617c486eca6401..94ec54b9aa08b60ab219d189c4445c600186c17a 100644 (file)
@@ -1898,7 +1898,8 @@ EXTERN listitem_T range_list_item;
 // Passed to an eval() function to enable evaluation.
 EXTERN evalarg_T EVALARG_EVALUATE
 # ifdef DO_INIT
-       = {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL}, NULL, NULL}
+       = {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL},
+                                                             NULL, NULL, NULL}
 # endif
        ;
 #endif
index 0ca9203406eb5c18b6ea139c62ce62830885861a..75ad127810b5c808e3da0068a1fa144f34e7bff3 100644 (file)
@@ -1882,6 +1882,9 @@ typedef struct {
     // pointer to the last line obtained with getsourceline()
     char_u     *eval_tofree;
 
+    // pointer to the last line of an inline function
+    char_u     *eval_tofree_cmdline;
+
     // pointer to the lines concatenated for a lambda.
     char_u     *eval_tofree_lambda;
 } evalarg_T;
index 51894dc101fea874a7d114befff2879b949a53a0..a53c4769c7274c51641bbd4bd4fa2d9ecdebbeed 100644 (file)
@@ -970,17 +970,18 @@ lambda_function_body(
 
     ga_init2(&newlines, (int)sizeof(char_u *), 10);
     if (get_function_body(&eap, &newlines, NULL, &line_to_free) == FAIL)
+    {
+       vim_free(cmdline);
        goto erret;
+    }
     if (cmdline != NULL)
     {
        // Something comes after the "}".
        *arg = eap.nextcmd;
-       if (evalarg->eval_cctx == NULL)
-       {
-           // Need to keep the line and free it/ later.
-           vim_free(evalarg->eval_tofree_lambda);
-           evalarg->eval_tofree_lambda = cmdline;
-       }
+
+       // "arg" points into cmdline, need to keep the line and free it later.
+       vim_free(evalarg->eval_tofree_cmdline);
+       evalarg->eval_tofree_cmdline = cmdline;
     }
     else
        *arg = (char_u *)"";
index cdce8cc767d91de845a475fc6dcb6366b298fc22..bdc23a4005527f420052d364994f6548dbcfd214 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2636,
 /**/
     2635,
 /**/
index 09b1fce83baea3ebcece3c359eec3d3aac0b931a..535de057c62dc937652f5c789a2de7ddcdba4c93 100644 (file)
@@ -3202,6 +3202,16 @@ compile_lambda(char_u **arg, cctx_T *cctx)
     // Compile the function into instructions.
     compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
 
+    // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
+    // points into it.  Point to the original line to avoid a dangling pointer.
+    if (evalarg.eval_tofree_cmdline != NULL)
+    {
+       size_t  off = *arg - evalarg.eval_tofree_cmdline;
+
+       *arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
+                                                                        + off;
+    }
+
     clear_evalarg(&evalarg, NULL);
 
     if (ufunc->uf_def_status == UF_COMPILED)