diff mbox series

[libgpiod,2/2] tests: add a test-case checking line-config memory usage

Message ID 20250424-line_config_mem_use-v1-2-fa0abdcf0cdf@linaro.org
State New
Headers show
Series line-config: don't allow memory usage to increase indefinitely | expand

Commit Message

Bartosz Golaszewski April 24, 2025, 12:06 p.m. UTC
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Add a test case making sure that repeatedly adding line settings to a
line-config object doesn't continuously inflate its size until OOM.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 configure.ac              |  1 +
 tests/tests-line-config.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index af5d53d..416ae28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,6 +172,7 @@  then
 	AC_CHECK_FUNC([tsearch], [], [FUNC_NOT_FOUND_LIB([tsearch])])
 	AC_CHECK_FUNC([tdestroy], [], [FUNC_NOT_FOUND_LIB([tdestroy])])
 	AC_CHECK_FUNC([tdelete], [], [FUNC_NOT_FOUND_LIB([tdelete])])
+	AC_CHECK_FUNC([setrlimit], [], [FUNC_NOT_FOUND_LIB([setrlimit])])
 	AC_CHECK_HEADERS([sys/utsname.h], [], [HEADER_NOT_FOUND_LIB([sys/utsname.h])])
 	AC_CHECK_HEADERS([sys/mount.h], [], [HEADER_NOT_FOUND_LIB([sys/mount.h])])
 	AC_CHECK_HEADERS([sys/prctl.h], [], [HEADER_NOT_FOUND_LIB([sys/prctl.h])])
diff --git a/tests/tests-line-config.c b/tests/tests-line-config.c
index b61a445..b510e0f 100644
--- a/tests/tests-line-config.c
+++ b/tests/tests-line-config.c
@@ -7,6 +7,8 @@ 
 #include <gpiod-test.h>
 #include <gpiod-test-common.h>
 #include <gpiosim-glib.h>
+#include <sys/resource.h>
+#include <unistd.h>
 
 #include "helpers.h"
 
@@ -469,3 +471,44 @@  GPIOD_TEST_CASE(handle_duplicate_offsets)
 	g_assert_cmpuint(retrieved[1], ==, 2);
 	g_assert_cmpuint(retrieved[2], ==, 3);
 }
+
+GPIOD_TEST_CASE(dont_allow_line_config_to_balloon_out_of_control)
+{
+	static const guint offsets[] = { 0, 2 };
+
+	g_autoptr(struct_gpiod_line_config) config = NULL;
+	g_autoptr(struct_gpiod_line_settings) settings = NULL;
+	struct rlimit rlim;
+	guint counter;
+	gint ret;
+
+	/*
+	 * Severly limit the available virtual memory and make sure that
+	 * adding settings for the same offsets repeatedly does not trigger
+	 * the OOM killer.
+	 */
+
+	if (g_test_subprocess()) {
+		config = gpiod_test_create_line_config_or_fail();
+		settings = gpiod_test_create_line_settings_or_fail();
+
+		rlim.rlim_cur = rlim.rlim_max = sysconf(_SC_PAGESIZE) * 100;
+		ret = setrlimit(RLIMIT_AS, &rlim);
+		g_assert_cmpint(ret, ==, 0);
+		gpiod_test_return_if_failed();
+
+		for (counter = 1000000; counter; counter--) {
+			gpiod_line_settings_set_direction(settings,
+					counter % 2 ?
+						GPIOD_LINE_DIRECTION_OUTPUT :
+						GPIOD_LINE_DIRECTION_INPUT);
+			gpiod_test_line_config_add_line_settings_or_fail(
+						config, offsets, 2, settings);
+		}
+
+		return;
+	}
+
+	g_test_trap_subprocess(NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
+	g_test_trap_assert_passed();
+}