]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
Add a test to check for issues with deeply nested objects, which can cause problems...
authorEric Hawicz <erh+git@nimenees.com>
Sun, 3 May 2026 16:16:56 +0000 (12:16 -0400)
committerEric Hawicz <erh+git@nimenees.com>
Mon, 4 May 2026 00:44:02 +0000 (20:44 -0400)
CMakeLists.txt
tests/CMakeLists.txt
tests/test_deep_nesting.c [new file with mode: 0644]
tests/test_deep_nesting.expected [new file with mode: 0644]
tests/test_deep_nesting.test [new symlink]

index 58ee9ede6da4361586264755977a543a7c52b500..c6695eb0089d4e665706d884215d15fb54640295 100644 (file)
@@ -267,6 +267,7 @@ if (HAVE_SYS_RANDOM_H)
 endif()
 if (HAVE_SYS_RESOURCE_H)
     check_symbol_exists(getrusage   "sys/resource.h" HAVE_GETRUSAGE)
+    check_symbol_exists(setrlimit   "sys/resource.h" HAVE_SETRLIMIT)
 endif()
 
 check_symbol_exists(strtoll     "stdlib.h" HAVE_STRTOLL)
index 46f802d91d6bca98b1d935cbdb86403b63c09f47..caff03f889bbb78efd42d50bb5903a5fbd0256bb 100644 (file)
@@ -21,6 +21,7 @@ set(ALL_TEST_NAMES
     test_charcase
     test_compare
     test_deep_copy
+    test_deep_nesting
     test_double_serializer
     test_float
     test_int_add
diff --git a/tests/test_deep_nesting.c b/tests/test_deep_nesting.c
new file mode 100644 (file)
index 0000000..90fa196
--- /dev/null
@@ -0,0 +1,84 @@
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include "config.h"
+
+#include "json.h"
+
+#define NESTING_DEPTH 100000
+
+static char *generate_json_string(void);
+static char *generate_json_string()
+{
+       char *str;
+       int depth = NESTING_DEPTH;
+       str = malloc(depth * 2 + 1);
+       memset(str, '[', depth);
+       memset(str + depth, ']', depth);
+       str[depth * 2] = '\0';
+       return str;
+}
+
+static void test_deep_nesting_put(const char *str);
+static void test_deep_nesting_put(const char *str)
+{
+       json_object *my_array;
+
+       struct json_tokener *tok = json_tokener_new_ex(NESTING_DEPTH);
+       my_array = json_tokener_parse_ex(tok, str, strlen(str) + 1);
+       printf("Parsed depth %d string to json_object: %s\n", NESTING_DEPTH, (my_array == NULL) ? "NO" : "yes");
+
+       json_object_put(my_array);
+       printf("Freed json_object\n");
+
+       json_tokener_free(tok);
+}
+
+static void test_deep_nesting_tostring(const char *str);
+static void test_deep_nesting_tostring(const char *str)
+{
+       json_object *my_array;
+
+       struct json_tokener *tok = json_tokener_new_ex(NESTING_DEPTH);
+       my_array = json_tokener_parse_ex(tok, str, strlen(str) + 1);
+       printf("Parsed depth %d string to json_object: %s\n", NESTING_DEPTH, (my_array == NULL) ? "NO" : "yes");
+
+       const char *res = json_object_to_json_string_ext(my_array, JSON_C_TO_STRING_PLAIN);
+       printf("Serialized to string of length %ld\n", (long)strlen(res));
+       json_object_put(my_array);
+       printf("Freed json_object\n");
+
+       json_tokener_free(tok);
+}
+
+int main(int argc, char **argv)
+{
+       char *str;      
+#ifdef HAVE_SETRLIMIT
+       struct rlimit rl;
+       rl.rlim_cur = 2048;
+       rl.rlim_max = 2048;
+       setrlimit(RLIMIT_STACK, &rl);
+#endif
+
+       str = generate_json_string();
+
+       MC_SET_DEBUG(1);
+
+       test_deep_nesting_put(str);
+
+       if (0) // TODO: make json_object_to_json_string non-recursive
+               test_deep_nesting_tostring(str);
+
+       free(str);
+
+       return EXIT_SUCCESS;
+}
diff --git a/tests/test_deep_nesting.expected b/tests/test_deep_nesting.expected
new file mode 100644 (file)
index 0000000..0790ee8
--- /dev/null
@@ -0,0 +1,2 @@
+Parsed depth 1000000 string to json_object: yes
+Freed json_object
diff --git a/tests/test_deep_nesting.test b/tests/test_deep_nesting.test
new file mode 120000 (symlink)
index 0000000..58a13f4
--- /dev/null
@@ -0,0 +1 @@
+test_basic.test
\ No newline at end of file