delfunc TryReturnOverlongString
endfunc
+" Memory allocation failure when registering a deferred function: the ga_grow()
+" in add_defer() fails, so the deferred function must not be registered and
+" "saved_name" must not leak
+func Test_defer_alloc_fail()
+ let g:defer_log = []
+ func DeferLogTarget()
+ call add(g:defer_log, 'ran')
+ endfunc
+ func CallWithDefer()
+ defer DeferLogTarget()
+ endfunc
+
+ call test_alloc_fail(GetAllocId('defer'), 0, 0)
+ call assert_fails('call CallWithDefer()', 'E342:')
+ call assert_equal([], g:defer_log)
+
+ " Without the injected failure it registers and runs at function exit.
+ call CallWithDefer()
+ call assert_equal(['ran'], g:defer_log)
+
+ delfunc DeferLogTarget
+ delfunc CallWithDefer
+ unlet g:defer_log
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
if (in_def_function())
{
if (add_defer_function(saved_name, argcount, argvars) == OK)
+ {
argcount = 0;
+ ret = OK;
+ }
}
else
{
if (current_funccal->fc_defer.ga_itemsize == 0)
ga_init2(¤t_funccal->fc_defer, sizeof(defer_T), 10);
- if (ga_grow(¤t_funccal->fc_defer, 1) == FAIL)
+ if (ga_grow_id(¤t_funccal->fc_defer, 1, aid_defer) == FAIL)
+ {
+ vim_free(saved_name);
goto theend;
+ }
dr = ((defer_T *)current_funccal->fc_defer.ga_data)
+ current_funccal->fc_defer.ga_len++;
dr->dr_name = saved_name;
--argcount;
dr->dr_argvars[argcount] = argvars[argcount];
}
+ ret = OK;
}
- ret = OK;
theend:
while (--argcount >= 0)