diff --git a/modules/module-lua-scripting/api/json.c b/modules/module-lua-scripting/api/json.c index 611c9248..2883a021 100644 --- a/modules/module-lua-scripting/api/json.c +++ b/modules/module-lua-scripting/api/json.c @@ -95,7 +95,7 @@ spa_json_is_object (lua_State *L) } static void -push_luajson (lua_State *L, WpSpaJson *json) +push_luajson (lua_State *L, WpSpaJson *json, gint n_recursions) { /* Null */ if (wp_spa_json_is_null (json)) { @@ -124,20 +124,20 @@ push_luajson (lua_State *L, WpSpaJson *json) } /* Array */ - else if (wp_spa_json_is_array (json)) { + else if (wp_spa_json_is_array (json) && n_recursions > 0) { g_auto (GValue) item = G_VALUE_INIT; g_autoptr (WpIterator) it = wp_spa_json_new_iterator (json); guint i = 1; lua_newtable (L); for (; wp_iterator_next (it, &item); g_value_unset (&item)) { WpSpaJson *j = g_value_get_boxed (&item); - push_luajson (L, j); + push_luajson (L, j, n_recursions - 1); lua_rawseti (L, -2, i++); } } /* Object */ - else if (wp_spa_json_is_object (json)) { + else if (wp_spa_json_is_object (json) && n_recursions > 0) { g_auto (GValue) item = G_VALUE_INIT; g_autoptr (WpIterator) it = wp_spa_json_new_iterator (json); lua_newtable (L); @@ -151,7 +151,7 @@ push_luajson (lua_State *L, WpSpaJson *json) if (!wp_iterator_next (it, &item)) break; value = g_value_get_boxed (&item); - push_luajson (L, value); + push_luajson (L, value, n_recursions - 1); lua_setfield (L, -2, key_str); } } @@ -168,7 +168,8 @@ static int spa_json_parse (lua_State *L) { WpSpaJson *json = wplua_checkboxed (L, 1, WP_TYPE_SPA_JSON); - push_luajson (L, json); + gint n_recursions = luaL_opt (L, luaL_checkinteger, 2, INT_MAX); + push_luajson (L, json, n_recursions); return 1; } diff --git a/tests/wplua/scripts/json.lua b/tests/wplua/scripts/json.lua index c0b5d638..0b18f648 100644 --- a/tests/wplua/scripts/json.lua +++ b/tests/wplua/scripts/json.lua @@ -186,3 +186,40 @@ assert (val.name == "wireplumber") assert (val.version[1] == 0) assert (val.version[2] == 4) assert (val.version[3] == 7) + +-- recursion limit +json = Json.Raw ("{ name = wireplumber, version = [0, 4, 15], args = { test = [0, 1] } }") + +val = json:parse (0) +assert (type (val) == "string") +assert (val == "{ name = wireplumber, version = [0, 4, 15], args = { test = [0, 1] } }") + +val = json:parse (1) +assert (type (val) == "table") +assert (val.name == "wireplumber") +assert (type (val.version) == "string") +assert (val.version == "[0, 4, 15]") +assert (type (val.args) == "string") +assert (val.args == "{ test = [0, 1] }") + +val = json:parse(2) +assert (type (val) == "table") +assert (val.name == "wireplumber") +assert (type (val.version) == "table") +assert (val.version[1] == 0) +assert (val.version[2] == 4) +assert (val.version[3] == 15) +assert (type (val.args) == "table") +assert (val.args.test == "[0, 1]") + +val = json:parse(3) +assert (type (val) == "table") +assert (val.name == "wireplumber") +assert (type (val.version) == "table") +assert (val.version[1] == 0) +assert (val.version[2] == 4) +assert (val.version[3] == 15) +assert (type (val.args) == "table") +assert (type (val.args.test) == "table") +assert (val.args.test[1] == 0) +assert (val.args.test[2] == 1)