]> granicus.if.org Git - vim/commitdiff
patch 8.2.1049: Vim9: leaking memory when using continuation line v8.2.1049
authorBram Moolenaar <Bram@vim.org>
Wed, 24 Jun 2020 18:34:03 +0000 (20:34 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 24 Jun 2020 18:34:03 +0000 (20:34 +0200)
Problem:    Vim9: leaking memory when using continuation line.
Solution:   Keep a pointer to the continuation line in evalarg_T.  Centralize
            checking for a next command.

23 files changed:
src/beval.c
src/buffer.c
src/clientserver.c
src/eval.c
src/evalvars.c
src/ex_docmd.c
src/ex_eval.c
src/filepath.c
src/findfile.c
src/fold.c
src/globals.h
src/if_ole.cpp
src/if_perl.xs
src/if_tcl.c
src/map.c
src/proto/eval.pro
src/quickfix.c
src/regexp.c
src/register.c
src/screen.c
src/structs.h
src/userfunc.c
src/version.c

index b7d9226e705f0cf8bcfc12a926c87885f2fd121d..dd7bc3cdc7b9ee29beb687d0da579c44dbab7e4b 100644 (file)
@@ -285,7 +285,7 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
            ++textwinlock;
 
            vim_free(result);
-           result = eval_to_string(bexpr, NULL, TRUE);
+           result = eval_to_string(bexpr, TRUE);
 
            // Remove one trailing newline, it is added when the result was a
            // list and it's hardly ever useful.  If the user really wants a
index f928412e85cbffd018236d6901a4f69488538841..40ca25dfa52042bfe784efd2c1120c30f1a98957 100644 (file)
@@ -4094,7 +4094,7 @@ build_stl_str_hl(
        tv.vval.v_number = wp->w_id;
        set_var((char_u *)"g:statusline_winid", &tv, FALSE);
 
-       usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox);
+       usefmt = eval_to_string_safe(fmt + 2, use_sandbox);
        if (usefmt == NULL)
            usefmt = fmt;
 
@@ -4434,7 +4434,7 @@ build_stl_str_hl(
            if (curwin != save_curwin)
                VIsual_active = FALSE;
 
-           str = eval_to_string_safe(p, &t, use_sandbox);
+           str = eval_to_string_safe(p, use_sandbox);
 
            curwin = save_curwin;
            curbuf = save_curbuf;
index cf35c8149f2ab1a84b7e67d4d11ef92cb93e9768..fbbeb6a4bf01f1193036d2fdf7e9c16cad9b6421 100644 (file)
@@ -86,7 +86,7 @@ eval_client_expr_to_string(char_u *expr)
     // to be typed.  Do generate errors so that try/catch works.
     ++emsg_silent;
 
-    res = eval_to_string(expr, NULL, TRUE);
+    res = eval_to_string(expr, TRUE);
 
     debug_break_level = save_dbl;
     redir_off = save_ro;
index ffb69de8d2180dfccf2050343c187d58048041c1..79944c8ca5e7c84b7b67caf59c2e3e8ebfaa9751 100644 (file)
@@ -161,7 +161,7 @@ eval_clear(void)
 eval_to_bool(
     char_u     *arg,
     int                *error,
-    char_u     **nextcmd,
+    exarg_T    *eap,
     int                skip)       // only parse, don't execute
 {
     typval_T   tv;
@@ -169,7 +169,7 @@ eval_to_bool(
 
     if (skip)
        ++emsg_skip;
-    if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE) == FAIL)
+    if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE) == FAIL)
        *error = TRUE;
     else
     {
@@ -317,7 +317,7 @@ eval_expr_to_bool(typval_T *expr, int *error)
     char_u *
 eval_to_string_skip(
     char_u     *arg,
-    char_u     **nextcmd,
+    exarg_T    *eap,
     int                skip)       // only parse, don't execute
 {
     typval_T   tv;
@@ -325,7 +325,7 @@ eval_to_string_skip(
 
     if (skip)
        ++emsg_skip;
-    if (eval0(arg, &tv, nextcmd, skip ? NULL : &EVALARG_EVALUATE)
+    if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE)
                                                               == FAIL || skip)
        retval = NULL;
     else
@@ -361,7 +361,6 @@ skip_expr(char_u **pp)
     char_u *
 eval_to_string(
     char_u     *arg,
-    char_u     **nextcmd,
     int                convert)
 {
     typval_T   tv;
@@ -371,7 +370,7 @@ eval_to_string(
     char_u     numbuf[NUMBUFLEN];
 #endif
 
-    if (eval0(arg, &tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
+    if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL)
        retval = NULL;
     else
     {
@@ -409,7 +408,6 @@ eval_to_string(
     char_u *
 eval_to_string_safe(
     char_u     *arg,
-    char_u     **nextcmd,
     int                use_sandbox)
 {
     char_u     *retval;
@@ -419,7 +417,7 @@ eval_to_string_safe(
     if (use_sandbox)
        ++sandbox;
     ++textwinlock;
-    retval = eval_to_string(arg, nextcmd, FALSE);
+    retval = eval_to_string(arg, FALSE);
     if (use_sandbox)
        --sandbox;
     --textwinlock;
@@ -459,12 +457,12 @@ eval_to_number(char_u *expr)
  * Returns NULL when there is an error.
  */
     typval_T *
-eval_expr(char_u *arg, char_u **nextcmd)
+eval_expr(char_u *arg, exarg_T *eap)
 {
     typval_T   *tv;
 
     tv = ALLOC_ONE(typval_T);
-    if (tv != NULL && eval0(arg, tv, nextcmd, &EVALARG_EVALUATE) == FAIL)
+    if (tv != NULL && eval0(arg, tv, eap, &EVALARG_EVALUATE) == FAIL)
        VIM_CLEAR(tv);
 
     return tv;
@@ -1418,7 +1416,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
 eval_for_line(
     char_u     *arg,
     int                *errp,
-    char_u     **nextcmdp,
+    exarg_T    *eap,
     int                skip)
 {
     forinfo_T  *fi;
@@ -1448,7 +1446,7 @@ eval_for_line(
 
     if (skip)
        ++emsg_skip;
-    if (eval0(skipwhite(expr + 2), &tv, nextcmdp, &evalarg) == OK)
+    if (eval0(skipwhite(expr + 2), &tv, eap, &evalarg) == OK)
     {
        *errp = FALSE;
        if (!skip)
@@ -1795,6 +1793,17 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
     return arg;
 }
 
+/*
+ * To be called when eval_next_non_blank() sets "getnext" to TRUE.
+ */
+    static char_u *
+eval_next_line(evalarg_T *evalarg)
+{
+    vim_free(evalarg->eval_tofree);
+    evalarg->eval_tofree = getsourceline(0, evalarg->eval_cookie, 0, TRUE);
+    return skipwhite(evalarg->eval_tofree);
+}
+
 /*
  * The "evaluate" argument: When FALSE, the argument is only parsed but not
  * executed.  The function may return OK, but the rettv will be of type
@@ -1813,7 +1822,7 @@ eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
 eval0(
     char_u     *arg,
     typval_T   *rettv,
-    char_u     **nextcmd,
+    exarg_T    *eap,
     evalarg_T  *evalarg)
 {
     int                ret;
@@ -1822,8 +1831,11 @@ eval0(
     int                called_emsg_before = called_emsg;
     int                flags = evalarg == NULL ? 0 : evalarg->eval_flags;
 
+    if (evalarg != NULL)
+       evalarg->eval_tofree = NULL;
     p = skipwhite(arg);
     ret = eval1(&p, rettv, evalarg);
+
     if (ret == FAIL || !ends_excmd2(arg, p))
     {
        if (ret != FAIL)
@@ -1841,8 +1853,27 @@ eval0(
            semsg(_(e_invexpr2), arg);
        ret = FAIL;
     }
-    if (nextcmd != NULL)
-       *nextcmd = check_nextcmd(p);
+
+    if (eap != NULL)
+       eap->nextcmd = check_nextcmd(p);
+
+    if (evalarg != NULL)
+    {
+       if (eap != NULL)
+       {
+           if (evalarg->eval_tofree != NULL)
+           {
+               // We may need to keep the original command line, e.g. for
+               // ":let" it has the variable names.  But we may also need the
+               // new one, "nextcmd" points into it.  Keep both.
+               vim_free(eap->cmdline_tofree);
+               eap->cmdline_tofree = *eap->cmdlinep;
+               *eap->cmdlinep = evalarg->eval_tofree;
+           }
+       }
+       else
+           vim_free(evalarg->eval_tofree);
+    }
 
     return ret;
 }
@@ -2305,7 +2336,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
        if (op != '+' && op != '-' && !concat)
            break;
        if (getnext)
-           *arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
+           *arg = eval_next_line(evalarg);
 
        if ((op != '+' || (rettv->v_type != VAR_LIST
                                                 && rettv->v_type != VAR_BLOB))
@@ -2497,7 +2528,7 @@ eval6(
        if (op != '*' && op != '/' && op != '%')
            break;
        if (getnext)
-           *arg = skipwhite(getsourceline(0, evalarg->eval_cookie, 0, TRUE));
+           *arg = eval_next_line(evalarg);
 
        if (evaluate)
        {
@@ -4734,7 +4765,6 @@ make_expanded_name(
     char_u     c1;
     char_u     *retval = NULL;
     char_u     *temp_result;
-    char_u     *nextcmd = NULL;
 
     if (expr_end == NULL || in_end == NULL)
        return NULL;
@@ -4743,8 +4773,8 @@ make_expanded_name(
     c1 = *in_end;
     *in_end = NUL;
 
-    temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE);
-    if (temp_result != NULL && nextcmd == NULL)
+    temp_result = eval_to_string(expr_start + 1, FALSE);
+    if (temp_result != NULL)
     {
        retval = alloc(STRLEN(temp_result) + (expr_start - in_start)
                                                   + (in_end - expr_end) + 1);
index 35c9dcb73e6f6cd5e5df28b06a6373cbb2ccc663..e64b44ed139e1bbb2204001deca2916dfe255ae9 100644 (file)
@@ -800,7 +800,7 @@ ex_let(exarg_T *eap)
            evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
            evalarg.eval_cookie = eap->getline == getsourceline
                                                          ? eap->cookie : NULL;
-           i = eval0(expr, &rettv, &eap->nextcmd, &evalarg);
+           i = eval0(expr, &rettv, eap, &evalarg);
            if (eap->skip)
                --emsg_skip;
        }
index 4755a01b48f98085a22555fc975673bfeb4b88aa..6c887fae1c2ea452afb05dfb04054a9c246aa8cb 100644 (file)
@@ -2609,6 +2609,7 @@ doend:
 
 #ifdef FEAT_EVAL
     --ex_nesting_level;
+    vim_free(ea.cmdline_tofree);
 #endif
 
     return ea.nextcmd;
@@ -4912,7 +4913,7 @@ ex_colorscheme(exarg_T *eap)
        if (expr != NULL)
        {
            ++emsg_off;
-           p = eval_to_string(expr, NULL, FALSE);
+           p = eval_to_string(expr, FALSE);
            --emsg_off;
            vim_free(expr);
        }
index cb32bd0791ae1efd0559c6a5ce519179a061ec74..8b8a2569579d68ad5a1879e1fa21446e76ce7060 100644 (file)
@@ -900,7 +900,7 @@ ex_eval(exarg_T *eap)
     evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
     evalarg.eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL;
 
-    if (eval0(eap->arg, &tv, &eap->nextcmd, &evalarg) == OK)
+    if (eval0(eap->arg, &tv, eap, &evalarg) == OK)
        clear_tv(&tv);
 }
 
@@ -929,7 +929,7 @@ ex_if(exarg_T *eap)
        skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0
                && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
 
-       result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+       result = eval_to_bool(eap->arg, &error, eap, skip);
 
        if (!skip && !error)
        {
@@ -1041,7 +1041,7 @@ ex_else(exarg_T *eap)
 
     if (eap->cmdidx == CMD_elseif)
     {
-       result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+       result = eval_to_bool(eap->arg, &error, eap, skip);
 
        // When throwing error exceptions, we want to throw always the first
        // of several errors in a row.  This is what actually happens when
@@ -1103,7 +1103,7 @@ ex_while(exarg_T *eap)
            /*
             * ":while bool-expr"
             */
-           result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
+           result = eval_to_bool(eap->arg, &error, eap, skip);
        }
        else
        {
@@ -1122,7 +1122,7 @@ ex_while(exarg_T *eap)
            else
            {
                // Evaluate the argument and get the info in a structure.
-               fi = eval_for_line(eap->arg, &error, &eap->nextcmd, skip);
+               fi = eval_for_line(eap->arg, &error, eap, skip);
                cstack->cs_forinfo[cstack->cs_idx] = fi;
            }
 
@@ -1322,7 +1322,7 @@ ex_throw(exarg_T *eap)
     char_u     *value;
 
     if (*arg != NUL && *arg != '|' && *arg != '\n')
-       value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
+       value = eval_to_string_skip(arg, eap, eap->skip);
     else
     {
        emsg(_(e_argreq));
index 1fe757e850273412f8f82cff86ce8ae049e80137..6644e9939db7e1f7aa37226e877c1ae551918504 100644 (file)
@@ -3083,7 +3083,7 @@ expand_backtick(
 
 #ifdef FEAT_EVAL
     if (*cmd == '=')       // `={expr}`: Expand expression
-       buffer = eval_to_string(cmd + 1, &p, TRUE);
+       buffer = eval_to_string(cmd + 1, TRUE);
     else
 #endif
        buffer = get_cmd_output(cmd, NULL,
index b153ed010cd6b08d0f57273f97e8ec58164b21db..190fc69dc6cb79e5d9ef2da403b79b3357dad294 100644 (file)
@@ -2079,7 +2079,7 @@ eval_includeexpr(char_u *ptr, int len)
     char_u     *res;
 
     set_vim_var_string(VV_FNAME, ptr, len);
-    res = eval_to_string_safe(curbuf->b_p_inex, NULL,
+    res = eval_to_string_safe(curbuf->b_p_inex,
                      was_set_insecurely((char_u *)"includeexpr", OPT_LOCAL));
     set_vim_var_string(VV_FNAME, NULL, 0);
     return res;
index d91203c75cb91ad53736070b1535974a1528fab6..043037fa64e5c71070e2d966aee72e18a7afec70 100644 (file)
@@ -1928,7 +1928,7 @@ get_foldtext(
            curbuf = wp->w_buffer;
 
            ++emsg_silent; // handle exceptions, but don't display errors
-           text = eval_to_string_safe(wp->w_p_fdt, NULL,
+           text = eval_to_string_safe(wp->w_p_fdt,
                         was_set_insecurely((char_u *)"foldtext", OPT_LOCAL));
            --emsg_silent;
 
index 8601e2b1e5345c687522d2b651cd97d909966ffd..c7f9794ab934238480a8f8fb473d49c6a10be53f 100644 (file)
@@ -1882,7 +1882,7 @@ EXTERN char windowsVersion[20] INIT(= {0});
 EXTERN listitem_T range_list_item;
 
 // Passed to an eval() function to enable evaluation.
-EXTERN evalarg_T EVALARG_EVALUATE INIT2(EVAL_EVALUATE, NULL);
+EXTERN evalarg_T EVALARG_EVALUATE INIT3(EVAL_EVALUATE, NULL, NULL);
 #endif
 
 #ifdef MSWIN
index 34ce232660321b490d27ac5d5ab24ec3db182c3e..e415a1924df44f9ef75aaff949c64a2b0cc53436 100644 (file)
@@ -388,7 +388,7 @@ CVim::Eval(BSTR expr, BSTR *result)
 
     /* Evaluate the expression */
     ++emsg_skip;
-    str = (char *)eval_to_string((char_u *)buffer, NULL, TRUE);
+    str = (char *)eval_to_string((char_u *)buffer, TRUE);
     --emsg_skip;
     vim_free(buffer);
     if (str == NULL)
index bf269cbcb05d6100a01016184f478da85de09915..cad571c5c7b8e98e8d22b4796f5215c453193d58 100644 (file)
@@ -832,7 +832,6 @@ msg_split(
     char_u *
 eval_to_string(
     char_u     *arg UNUSED,
-    char_u     **nextcmd UNUSED,
     int                dolist UNUSED)
 {
     return NULL;
@@ -1562,7 +1561,7 @@ Eval(str)
     PREINIT:
        char_u *value;
     PPCODE:
-       value = eval_to_string((char_u *)str, (char_u **)0, TRUE);
+       value = eval_to_string((char_u *)str, TRUE);
        if (value == NULL)
        {
            XPUSHs(sv_2mortal(newSViv(0)));
index c274b26750d111568429105c9cb7f19d7e82ba57..2775221f4696c7d7c129862d15c8a9597cf19f68 100644 (file)
@@ -1373,7 +1373,7 @@ tclvimexpr(
 
 #ifdef FEAT_EVAL
     expr = Tcl_GetStringFromObj(objv[objn], NULL);
-    str = (char *)eval_to_string((char_u *)expr, NULL, TRUE);
+    str = (char *)eval_to_string((char_u *)expr, TRUE);
     if (str == NULL)
        Tcl_SetResult(interp, _("invalid expression"), TCL_STATIC);
     else
index 4f0c8709af87b243926608adf23d331498a3db88..26fce68d8cc041bb5779974dad195c07cca836a3 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -1614,7 +1614,7 @@ eval_map_expr(
     save_cursor = curwin->w_cursor;
     save_msg_col = msg_col;
     save_msg_row = msg_row;
-    p = eval_to_string(expr, NULL, FALSE);
+    p = eval_to_string(expr, FALSE);
     --textwinlock;
     --ex_normal_lock;
     curwin->w_cursor = save_cursor;
index 4fb04eb1fcc5a13889ee6f4456548d1db889cea5..87e447808bc95d94a4407a05ef52ad2becfc2cf6 100644 (file)
@@ -3,16 +3,16 @@ varnumber_T num_divide(varnumber_T n1, varnumber_T n2);
 varnumber_T num_modulus(varnumber_T n1, varnumber_T n2);
 void eval_init(void);
 void eval_clear(void);
-int eval_to_bool(char_u *arg, int *error, char_u **nextcmd, int skip);
+int eval_to_bool(char_u *arg, int *error, exarg_T *eap, int skip);
 int eval_expr_valid_arg(typval_T *tv);
 int eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv);
 int eval_expr_to_bool(typval_T *expr, int *error);
-char_u *eval_to_string_skip(char_u *arg, char_u **nextcmd, int skip);
+char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
 int skip_expr(char_u **pp);
-char_u *eval_to_string(char_u *arg, char_u **nextcmd, int convert);
-char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox);
+char_u *eval_to_string(char_u *arg, int convert);
+char_u *eval_to_string_safe(char_u *arg, int use_sandbox);
 varnumber_T eval_to_number(char_u *expr);
-typval_T *eval_expr(char_u *arg, char_u **nextcmd);
+typval_T *eval_expr(char_u *arg, exarg_T *eap);
 int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv);
 varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv);
 void *call_func_retstr(char_u *func, int argc, typval_T *argv);
@@ -21,13 +21,13 @@ int eval_foldexpr(char_u *arg, int *cp);
 char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
 void clear_lval(lval_T *lp);
 void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op);
-void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip);
+void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, int skip);
 int next_for_item(void *fi_void, char_u *arg);
 void free_for_info(void *fi_void);
 void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx);
 int pattern_match(char_u *pat, char_u *text, int ic);
-int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, evalarg_T *evalarg);
-int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg_in);
+int eval0(char_u *arg, typval_T *rettv, exarg_T *eap, evalarg_T *evalarg);
+int eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
 void eval_addblob(typval_T *tv1, typval_T *tv2);
 int eval_addlist(typval_T *tv1, typval_T *tv2);
 char_u *partial_name(partial_T *pt);
index ba54fab9c736c2595cd5b7be42a39ce7fdbfa107..3bd0f75e245e1b98b3143be69f80b4d08d7d3388 100644 (file)
@@ -7680,7 +7680,7 @@ ex_cexpr(exarg_T *eap)
 
     // Evaluate the expression.  When the result is a string or a list we can
     // use it to fill the errorlist.
-    tv = eval_expr(eap->arg, &eap->nextcmd);
+    tv = eval_expr(eap->arg, eap);
     if (tv != NULL)
     {
        if ((tv->v_type == VAR_STRING && tv->vval.v_string != NULL)
index de0b0fad43700241a7588d58a6a4a345307dddf8..229f6ef2b7cb643d5f276f834371d6a6f4bf2e05 100644 (file)
@@ -2066,7 +2066,7 @@ vim_regsub_both(
                clear_tv(&rettv);
            }
            else
-               eval_result = eval_to_string(source + 2, NULL, TRUE);
+               eval_result = eval_to_string(source + 2, TRUE);
 
            if (eval_result != NULL)
            {
index 49f7a7c86af67a2293ec15c4571f1a2b1fc771f8..66dd0cca65eefbb490926e6e1d76e64b458f131a 100644 (file)
@@ -136,7 +136,7 @@ get_expr_line(void)
        return expr_copy;
 
     ++nested;
-    rv = eval_to_string(expr_copy, NULL, TRUE);
+    rv = eval_to_string(expr_copy, TRUE);
     --nested;
     vim_free(expr_copy);
     return rv;
index ea7aaa67f8580cb99ae72ba26197f5b0174dd3fb..01d6257b7cb345d1799833e8a4b4bf4651a6f1a7 100644 (file)
@@ -1148,7 +1148,7 @@ get_keymap_str(
        curwin = wp;
        STRCPY(buf, "b:keymap_name");   // must be writable
        ++emsg_skip;
-       s = p = eval_to_string(buf, NULL, FALSE);
+       s = p = eval_to_string(buf, FALSE);
        --emsg_skip;
        curbuf = old_curbuf;
        curwin = old_curwin;
index 0ac486406be6f54e2fdaefd855d7de681a64034e..39508873550b8819bf889450507936822011be60 100644 (file)
@@ -1753,6 +1753,9 @@ typedef struct {
 
     // copied from exarg_T when "getline" is "getsourceline". Can be NULL.
     void       *eval_cookie;   // argument for getline()
+
+    // pointer to the line obtained with getsourceline()
+    char_u     *eval_tofree;
 } evalarg_T;
 
 // Flags for expression evaluation.
index a27c68d04128859bc3d1141e5492b590f786c0be..c6a8a8cd3d336f09512eec65c905d6dfa1d706ca 100644 (file)
@@ -3716,7 +3716,7 @@ ex_return(exarg_T *eap)
 
     eap->nextcmd = NULL;
     if ((*arg != NUL && *arg != '|' && *arg != '\n')
-                       && eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL)
+                                 && eval0(arg, &rettv, eap, &evalarg) != FAIL)
     {
        if (!eap->skip)
            returning = do_return(eap, FALSE, TRUE, &rettv);
@@ -3773,7 +3773,7 @@ ex_call(exarg_T *eap)
        // instead to skip to any following command, e.g. for:
        //   :if 0 | call dict.foo().bar() | endif
        ++emsg_skip;
-       if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL)
+       if (eval0(eap->arg, &rettv, eap, NULL) != FAIL)
            clear_tv(&rettv);
        --emsg_skip;
        return;
index 4e2c5537998311584d1fbaacce8683463b12be0d..d39c1b07c059239782a61b257cadd2693c0deeac 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1049,
 /**/
     1048,
 /**/