-*options.txt* For Vim version 9.2. Last change: 2026 Mar 22
+*options.txt* For Vim version 9.2. Last change: 2026 Mar 23
VIM REFERENCE MANUAL by Bram Moolenaar
Increasing this limit above 200 also changes the maximum for Ex
command recursion, see |E169|.
See also |:function|.
- Also used for maximum depth of callback functions.
+ Also used for maximum depth of callback functions and encoding and
+ decoding of deeply nested json data.
*'maxmapdepth'* *'mmd'* *E223*
'maxmapdepth' 'mmd' number (default 1000)
// E130 unused
EXTERN char e_cannot_delete_function_str_it_is_in_use[]
INIT(= N_("E131: Cannot delete function %s: It is in use"));
-EXTERN char e_function_call_depth_is_higher_than_macfuncdepth[]
+EXTERN char e_function_call_depth_is_higher_than_maxfuncdepth[]
INIT(= N_("E132: Function call depth is higher than 'maxfuncdepth'"));
EXTERN char e_return_not_inside_function[]
INIT(= N_("E133: :return not inside a function"));
#if defined(FEAT_EVAL)
-static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
+static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options, int depth);
/*
* Encode "val" into a JSON format string.
static int
json_encode_gap(garray_T *gap, typval_T *val, int options)
{
- if (json_encode_item(gap, val, get_copyID(), options) == FAIL)
+ if (json_encode_item(gap, val, get_copyID(), options, 0) == FAIL)
{
ga_clear(gap);
gap->ga_data = vim_strsave((char_u *)"");
* Return FAIL or OK.
*/
static int
-json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
+json_encode_item(garray_T *gap, typval_T *val, int copyID, int options, int depth)
{
char_u numbuf[NUMBUFLEN];
char_u *res;
dict_T *d;
int i;
+ if (depth > p_mfd)
+ {
+ emsg(_(e_function_call_depth_is_higher_than_maxfuncdepth));
+ return FAIL;
+ }
+
switch (val->v_type)
{
case VAR_BOOL:
for (li = l->lv_first; li != NULL && !got_int; )
{
if (json_encode_item(gap, &li->li_tv, copyID,
- options & JSON_JS) == FAIL)
+ options & JSON_JS,
+ depth + 1) == FAIL)
return FAIL;
if ((options & JSON_JS)
&& li->li_next == NULL
{
typval_T *t_item = TUPLE_ITEM(tuple, i);
if (json_encode_item(gap, t_item, copyID,
- options & JSON_JS) == FAIL)
+ options & JSON_JS,
+ depth + 1) == FAIL)
return FAIL;
if ((options & JSON_JS)
write_string(gap, hi->hi_key);
ga_append(gap, ':');
if (json_encode_item(gap, &dict_lookup(hi)->di_tv,
- copyID, options | JSON_NO_NONE) == FAIL)
+ copyID, options | JSON_NO_NONE,
+ depth + 1) == FAIL)
return FAIL;
}
ga_append(gap, '}');
retval = FAIL;
break;
}
+ if (stack.ga_len >= p_mfd)
+ {
+ emsg(_(e_function_call_depth_is_higher_than_maxfuncdepth));
+ retval = FAIL;
+ break;
+ }
if (ga_grow(&stack, 1) == FAIL)
{
retval = FAIL;
retval = FAIL;
break;
}
+ if (stack.ga_len >= p_mfd)
+ {
+ emsg(_(e_function_call_depth_is_higher_than_maxfuncdepth));
+ retval = FAIL;
+ break;
+ }
if (ga_grow(&stack, 1) == FAIL)
{
retval = FAIL;
call assert_equal(4000, len(json))
endfunc
+func Test_json_encode_depth()
+ let save_mfd = &maxfuncdepth
+ set maxfuncdepth=10
+
+ " Create a deeply nested list that exceeds maxfuncdepth.
+ let l = []
+ let d = {}
+ for i in range(20)
+ let l = [l]
+ let d = {1: d}
+ endfor
+ call assert_fails('call json_encode(l)', 'E132:')
+ call assert_fails('call json_encode(d)', 'E132:')
+
+ let &maxfuncdepth = save_mfd
+endfunc
+
+func Test_json_decode_depth()
+ let save_mfd = &maxfuncdepth
+ set maxfuncdepth=10
+
+ let deep_json = repeat('[', 20) .. '1' .. repeat(']', 20)
+ call assert_fails('call json_decode(deep_json)', 'E132:')
+
+ let deep_json = repeat('{"a":', 20) .. '1' .. repeat('}', 20)
+ call assert_fails('call json_decode(deep_json)', 'E132:')
+
+ let &maxfuncdepth = save_mfd
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab