To: vim_dev@googlegroups.com Subject: Patch 8.2.2864 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 var FuncList: list = [() => 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 -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///