Patch 8.2.2864
Problem: Vim9: crash when using inline function.
Solution: Check for NULL pointer. Make using inline function work inside
lambda. (closes #8217)
Files: src/userfunc.c, src/testdir/test_vim9_func.vim
*** ../vim-8.2.2863/src/userfunc.c 2021-04-14 17:06:39.924955017 +0200
--- src/userfunc.c 2021-05-18 00:41:41.049212208 +0200
***************
*** 606,611 ****
--- 606,612 ----
/*
* Read the body of a function, put every line in "newlines".
+ * This stops at "}", "endfunction" or "enddef".
* "newlines" must already have been initialized.
* "eap->cmdidx" is CMD_function, CMD_def or CMD_block;
*/
***************
*** 945,953 ****
line_arg = NULL;
}
! // Don't define the function when skipping commands or when an error was
! // detected.
! if (!eap->skip && !did_emsg)
ret = OK;
theend:
--- 946,953 ----
line_arg = NULL;
}
! // Return OK when no error was detected.
! if (!did_emsg)
ret = OK;
theend:
***************
*** 960,965 ****
--- 960,966 ----
/*
* Handle the body of a lambda. *arg points to the "{", process statements
* until the matching "}".
+ * When not evaluating "newargs" is NULL.
* When successful "rettv" is set to a funcref.
*/
static int
***************
*** 974,979 ****
--- 975,981 ----
char_u *ret_type)
{
int evaluate = (evalarg->eval_flags & EVAL_EVALUATE);
+ garray_T *gap = &evalarg->eval_ga;
ufunc_T *ufunc = NULL;
exarg_T eap;
garray_T newlines;
***************
*** 1010,1015 ****
--- 1012,1063 ----
vim_free(cmdline);
goto erret;
}
+
+ // When inside a lambda must add the function lines to evalarg.eval_ga.
+ evalarg->eval_break_count += newlines.ga_len;
+ if (gap->ga_itemsize > 0)
+ {
+ int idx;
+ char_u *last;
+ size_t plen;
+ char_u *pnl;
+
+ for (idx = 0; idx < newlines.ga_len; ++idx)
+ {
+ char_u *p = skipwhite(((char_u **)newlines.ga_data)[idx]);
+
+ if (ga_grow(gap, 1) == FAIL)
+ goto erret;
+
+ // Going to concatenate the lines after parsing. For an empty or
+ // comment line use an empty string.
+ // Insert NL characters at the start of each line, the string will
+ // be split again later in .get_lambda_tv().
+ if (*p == NUL || vim9_comment_start(p))
+ p = (char_u *)"";
+ plen = STRLEN(p);
+ pnl = vim_strnsave((char_u *)"\n", plen + 1);
+ if (pnl != NULL)
+ mch_memmove(pnl + 1, p, plen + 1);
+ ((char_u **)gap->ga_data)[gap->ga_len] = pnl;
+ ++gap->ga_len;
+ }
+ if (ga_grow(gap, 1) == FAIL)
+ goto erret;
+ if (cmdline != NULL)
+ // more is following after the "}", which was skipped
+ last = cmdline;
+ else
+ // nothing is following the "}"
+ last = (char_u *)"}";
+ plen = STRLEN(last);
+ pnl = vim_strnsave((char_u *)"\n", plen + 1);
+ if (pnl != NULL)
+ mch_memmove(pnl + 1, last, plen + 1);
+ ((char_u **)gap->ga_data)[gap->ga_len] = pnl;
+ ++gap->ga_len;
+ }
+
if (cmdline != NULL)
{
// Something comes after the "}".
***************
*** 1022,1027 ****
--- 1070,1081 ----
else
*arg = (char_u *)"";
+ if (!evaluate)
+ {
+ ret = OK;
+ goto erret;
+ }
+
name = get_lambda_name();
ufunc = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
if (ufunc == NULL)
***************
*** 1078,1084 ****
SOURCING_LNUM = lnum_save;
vim_free(line_to_free);
ga_clear_strings(&newlines);
! ga_clear_strings(newargs);
ga_clear_strings(default_args);
if (ufunc != NULL)
{
--- 1132,1139 ----
SOURCING_LNUM = lnum_save;
vim_free(line_to_free);
ga_clear_strings(&newlines);
! if (newargs != NULL)
! ga_clear_strings(newargs);
ga_clear_strings(default_args);
if (ufunc != NULL)
{
***************
*** 1222,1227 ****
--- 1277,1283 ----
int len;
int flags = 0;
char_u *p;
+ char_u *line_end;
char_u *name = get_lambda_name();
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
***************
*** 1236,1249 ****
if (ga_grow(&newlines, 1) == FAIL)
goto errret;
! // Add "return " before the expression.
! len = 7 + (int)(end - start) + 1;
p = alloc(len);
if (p == NULL)
goto errret;
((char_u **)(newlines.ga_data))[newlines.ga_len++] = p;
STRCPY(p, "return ");
! vim_strncpy(p + 7, start, end - start);
if (strstr((char *)p + 7, "a:") == NULL)
// No a: variables are used for sure.
flags |= FC_NOARGS;
--- 1292,1328 ----
if (ga_grow(&newlines, 1) == FAIL)
goto errret;
! // If there are line breaks, we need to split up the string.
! line_end = vim_strchr(start, '\n');
! if (line_end == NULL)
! line_end = end;
!
! // Add "return " before the expression (or the first line).
! len = 7 + (int)(line_end - start) + 1;
p = alloc(len);
if (p == NULL)
goto errret;
((char_u **)(newlines.ga_data))[newlines.ga_len++] = p;
STRCPY(p, "return ");
! vim_strncpy(p + 7, start, line_end - start);
!
! if (line_end != end)
! {
! // Add more lines, split by line breaks. Thus is used when a
! // lambda with { cmds } is encountered.
! while (*line_end == '\n')
! {
! if (ga_grow(&newlines, 1) == FAIL)
! goto errret;
! start = line_end + 1;
! line_end = vim_strchr(start, '\n');
! if (line_end == NULL)
! line_end = end;
! ((char_u **)(newlines.ga_data))[newlines.ga_len++] =
! vim_strnsave(start, line_end - start);
! }
! }
!
if (strstr((char *)p + 7, "a:") == NULL)
// No a: variables are used for sure.
flags |= FC_NOARGS;
*** ../vim-8.2.2863/src/testdir/test_vim9_func.vim 2021-04-28
20:40:39.799852470 +0200
--- src/testdir/test_vim9_func.vim 2021-05-18 11:46:35.848516324 +0200
***************
*** 2102,2107 ****
--- 2102,2121 ----
CheckScriptSuccess(lines)
enddef
+ def Test_nested_inline_lambda()
+ # TODO: use the "text" argument
+ var lines =<< trim END
+ vim9script
+ def F(text: string): func(string): func(string): string
+ return (arg: string): func(string): string => ((sep: string): string
=> {
+ return sep .. arg
+ })
+ enddef
+ assert_equal('--there', F('unused')('there')('--'))
+ END
+ CheckScriptSuccess(lines)
+ enddef
+
def Shadowed(): list<number>
var FuncList: list<func: number> = [() => 42]
return FuncList->mapnew((_, Shadowed) => Shadowed())
*** ../vim-8.2.2863/src/version.c 2021-05-17 00:22:01.993641079 +0200
--- src/version.c 2021-05-17 15:52:31.845575800 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2864,
/**/
--
"Intelligence has much less practical application than you'd think."
-- Scott Adams, Dilbert.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202105180948.14I9mgu04020439%40masaka.moolenaar.net.