comparison src/vim9cmds.c @ 30166:d1c04b4dc60d v9.0.0419

patch 9.0.0419: the :defer command does not check the function arguments Commit: https://github.com/vim/vim/commit/169003289fb4b2ad18fd7f5807e0d05efff0be85 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Sep 8 19:51:45 2022 +0100 patch 9.0.0419: the :defer command does not check the function arguments Problem: The :defer command does not check the function argument count and types. Solution: Check the function arguments when adding a deferred function.
author Bram Moolenaar <Bram@vim.org>
date Thu, 08 Sep 2022 21:00:04 +0200
parents 4eac06fb0191
children 6472aa128651
comparison
equal deleted inserted replaced
30165:27820ff1eaf4 30166:d1c04b4dc60d
1683 1683
1684 return skipwhite(p); 1684 return skipwhite(p);
1685 } 1685 }
1686 1686
1687 /* 1687 /*
1688 * Get the local variable index for deferred function calls.
1689 * Reserve it when not done already.
1690 * Returns zero for failure.
1691 */
1692 int
1693 get_defer_var_idx(cctx_T *cctx)
1694 {
1695 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1696 + cctx->ctx_ufunc->uf_dfunc_idx;
1697 if (dfunc->df_defer_var_idx == 0)
1698 {
1699 lvar_T *lvar = reserve_local(cctx, (char_u *)"@defer@", 7,
1700 TRUE, &t_list_any);
1701 if (lvar == NULL)
1702 return 0;
1703 dfunc->df_defer_var_idx = lvar->lv_idx + 1;
1704 }
1705 return dfunc->df_defer_var_idx;
1706 }
1707
1708 /*
1709 * Compile "defer func(arg)". 1688 * Compile "defer func(arg)".
1710 */ 1689 */
1711 char_u * 1690 char_u *
1712 compile_defer(char_u *arg_start, cctx_T *cctx) 1691 compile_defer(char_u *arg_start, cctx_T *cctx)
1713 { 1692 {
1714 char_u *p; 1693 char_u *paren;
1715 char_u *arg = arg_start; 1694 char_u *arg = arg_start;
1716 int argcount = 0; 1695 int argcount = 0;
1717 int defer_var_idx; 1696 int defer_var_idx;
1718 type_T *type; 1697 type_T *type;
1719 int func_idx; 1698 int func_idx;
1720 1699
1721 // Get a funcref for the function name. 1700 // Get a funcref for the function name.
1722 // TODO: better way to find the "(". 1701 // TODO: better way to find the "(".
1723 p = vim_strchr(arg, '('); 1702 paren = vim_strchr(arg, '(');
1724 if (p == NULL) 1703 if (paren == NULL)
1725 { 1704 {
1726 semsg(_(e_missing_parenthesis_str), arg); 1705 semsg(_(e_missing_parenthesis_str), arg);
1727 return NULL; 1706 return NULL;
1728 } 1707 }
1729 *p = NUL; 1708 *paren = NUL;
1730 func_idx = find_internal_func(arg); 1709 func_idx = find_internal_func(arg);
1731 if (func_idx >= 0) 1710 if (func_idx >= 0)
1732 // TODO: better type 1711 // TODO: better type
1733 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx), 1712 generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
1734 &t_func_any, FALSE); 1713 &t_func_any, FALSE);
1735 else if (compile_expr0(&arg, cctx) == FAIL) 1714 else if (compile_expr0(&arg, cctx) == FAIL)
1736 return NULL; 1715 return NULL;
1737 *p = '('; 1716 *paren = '(';
1738 1717
1739 // check for function type 1718 // check for function type
1740 type = get_type_on_stack(cctx, 0); 1719 type = get_type_on_stack(cctx, 0);
1741 if (type->tt_type != VAR_FUNC) 1720 if (type->tt_type != VAR_FUNC)
1742 { 1721 {
1743 emsg(_(e_function_name_required)); 1722 emsg(_(e_function_name_required));
1744 return NULL; 1723 return NULL;
1745 } 1724 }
1746 1725
1747 // compile the arguments 1726 // compile the arguments
1748 arg = skipwhite(p + 1); 1727 arg = skipwhite(paren + 1);
1749 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL) 1728 if (compile_arguments(&arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL)
1750 return NULL; 1729 return NULL;
1751 1730
1752 // TODO: check argument count with "type" 1731 if (func_idx >= 0)
1732 {
1733 type2_T *argtypes = NULL;
1734 type2_T shuffled_argtypes[MAX_FUNC_ARGS];
1735
1736 if (check_internal_func_args(cctx, func_idx, argcount, FALSE,
1737 &argtypes, shuffled_argtypes) == FAIL)
1738 return NULL;
1739 }
1740 else if (check_func_args_from_type(cctx, type, argcount, TRUE,
1741 arg_start) == FAIL)
1742 return NULL;
1753 1743
1754 defer_var_idx = get_defer_var_idx(cctx); 1744 defer_var_idx = get_defer_var_idx(cctx);
1755 if (defer_var_idx == 0) 1745 if (defer_var_idx == 0)
1756 return NULL; 1746 return NULL;
1757 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL) 1747 if (generate_DEFER(cctx, defer_var_idx - 1, argcount) == FAIL)