[PATCH v3 03/11] sampling-asan: Add test cases for sampling-asan
Sung-hun Kim
sfoon.kim@samsung.com
Tue Sep 30 06:46:52 GMT 2025
Test cases are categorized into two groups:
1. Testing basic functionalities of sampling-asan
2. Testing creation of proper memory bug reports
Memory bug types are defined in samasan_error.h. If you wonder about it,
please refer the header file.
Signed-off-by: Sung-hun Kim <sfoon.kim@samsung.com>
---
sampling-asan/Makefile | 10 +-
sampling-asan/tst-allocate.c | 209 ++++++++++++++++++++++++
sampling-asan/tst-block-sizes.c | 68 ++++++++
sampling-asan/tst-chunk-pick.c | 103 ++++++++++++
sampling-asan/tst-common.c | 88 ++++++++++
sampling-asan/tst-double-free.c | 63 +++++++
sampling-asan/tst-init.c | 120 ++++++++++++++
sampling-asan/tst-invalid-access.c | 71 ++++++++
sampling-asan/tst-invalid-access2.c | 66 ++++++++
sampling-asan/tst-invalid-free.c | 65 ++++++++
sampling-asan/tst-invalid-free2.c | 65 ++++++++
sampling-asan/tst-invalid-write.c | 69 ++++++++
sampling-asan/tst-out-of-memory-pool.c | 61 +++++++
sampling-asan/tst-partition-sizes.c | 88 ++++++++++
sampling-asan/tst-pause-on-fork.c | 139 ++++++++++++++++
sampling-asan/tst-sampling.c | 82 ++++++++++
sampling-asan/tst-threaded-allocation.c | 90 ++++++++++
sampling-asan/tst-use-after-free.c | 66 ++++++++
18 files changed, 1522 insertions(+), 1 deletion(-)
create mode 100644 sampling-asan/tst-allocate.c
create mode 100644 sampling-asan/tst-block-sizes.c
create mode 100644 sampling-asan/tst-chunk-pick.c
create mode 100644 sampling-asan/tst-common.c
create mode 100644 sampling-asan/tst-double-free.c
create mode 100644 sampling-asan/tst-init.c
create mode 100644 sampling-asan/tst-invalid-access.c
create mode 100644 sampling-asan/tst-invalid-access2.c
create mode 100644 sampling-asan/tst-invalid-free.c
create mode 100644 sampling-asan/tst-invalid-free2.c
create mode 100644 sampling-asan/tst-invalid-write.c
create mode 100644 sampling-asan/tst-out-of-memory-pool.c
create mode 100644 sampling-asan/tst-partition-sizes.c
create mode 100644 sampling-asan/tst-pause-on-fork.c
create mode 100644 sampling-asan/tst-sampling.c
create mode 100644 sampling-asan/tst-threaded-allocation.c
create mode 100644 sampling-asan/tst-use-after-free.c
diff --git a/sampling-asan/Makefile b/sampling-asan/Makefile
index 70f639dab5..b0d408af30 100644
--- a/sampling-asan/Makefile
+++ b/sampling-asan/Makefile
@@ -25,5 +25,13 @@ dist-headers := samasan.h
headers := $(dist-headers)
routines := samasan_allocate samasan_error samasan_sampling samasan_common \
samasan_init samasan_report samasan_backtrace samasan_fault_handler
+tests := tst-allocate tst-sampling tst-threaded-allocation tst-init \
+ tst-double-free tst-use-after-free tst-invalid-write \
+ tst-block-sizes tst-partition-sizes tst-invalid-access \
+ tst-invalid-access2 tst-out-of-memory-pool \
+ tst-invalid-free tst-invalid-free2 tst-pause-on-fork \
+ tst-chunk-pick
-include ../Rules
+$(objpfx)tst-threaded-allocation: $(shared-thread-library)
+
+include ../Rules
\ No newline at end of file
diff --git a/sampling-asan/tst-allocate.c b/sampling-asan/tst-allocate.c
new file mode 100644
index 0000000000..b0598a5fc5
--- /dev/null
+++ b/sampling-asan/tst-allocate.c
@@ -0,0 +1,209 @@
+/* Test and verify allocations in sampling-asan.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+static void
+test_allocations (void)
+{
+ const size_t zero_size = 0;
+ const size_t allocation_size = 4096;
+ void *ptr;
+
+ ptr = samasan_allocate (zero_size);
+ TEST_VERIFY(ptr == NULL);
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr != NULL);
+ samasan_free (ptr);
+}
+
+static void
+test_too_large_allocation (void)
+{
+ const size_t allocation_size = 4096 + 4096;
+ void *ptr;
+
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr == NULL);
+}
+
+static void
+test_multiple_allocations (void)
+{
+#define MAX_ALLOCATIONS 101
+ const size_t allocation_size = 512;
+ void *ptr[MAX_ALLOCATIONS] = { NULL, };
+
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ ptr[i] = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr[MAX_ALLOCATIONS - 1] == NULL);
+ for (int i = 0; i < MAX_ALLOCATIONS - 1; i++)
+ samasan_free (ptr[i]);
+#undef MAX_ALLOCATIONS
+}
+
+static void
+test_allocation_and_free (void)
+{
+#define MAX_ALLOCATIONS 100
+ const size_t allocation_size = 512;
+ void *ptr[MAX_ALLOCATIONS] = { NULL, };
+
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ {
+ ptr[i] = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr[i] != NULL);
+ }
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ samasan_free (ptr[i]);
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ {
+ ptr[i] = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr[i] != NULL);
+ }
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ samasan_free (ptr[i]);
+#undef MAX_ALLOCATIONS
+}
+
+static void
+test_allocation_use_free_repeat (void)
+{
+#define NR_REPEAT 100
+ const size_t allocation_size = 512;
+ void *ptr;
+
+ for (int i = 0; i < NR_REPEAT; i++)
+ {
+ char *cptr;
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr != NULL);
+ cptr = (char *) ptr;
+ for (int j = 0; j < allocation_size; j++)
+ cptr[j] = 'a';
+ samasan_free( ptr);
+ }
+#undef NR_REPEAT
+}
+
+static void
+test_out_of_bound_pointer (void)
+{
+#define OUT_OF_BOUND_OFFSET (4096 * 100)
+ const size_t allocation_size = 512;
+ void *ptr, *oob_ptr;
+
+ ptr = samasan_allocate (allocation_size);
+ oob_ptr = ptr + OUT_OF_BOUND_OFFSET;
+ TEST_VERIFY (samasan_is_pointer_in_sampling_pool (oob_ptr) == false);
+ samasan_free (ptr);
+#undef OUT_OF_BOUND_OFFSET
+}
+
+static void
+test_allocated_size (void)
+{
+ const size_t allocation_size1 = 512;
+ const size_t allocation_size2 = 1023;
+ void *ptr1, *ptr2;
+
+ ptr1 = samasan_allocate (allocation_size1);
+ ptr2 = samasan_allocate (allocation_size2);
+
+ TEST_VERIFY (samasan_get_size (ptr1) == allocation_size1);
+ TEST_VERIFY (samasan_get_size (ptr2) == allocation_size2);
+
+ samasan_free (ptr1);
+ samasan_free (ptr2);
+}
+
+static void
+test_wrong_get_size (void)
+{
+#define OUT_OF_BOUND_OFFSET (4096 * 100)
+ const size_t allocation_size = 512;
+ void *ptr, *oob_ptr;
+
+ ptr = samasan_allocate (allocation_size);
+ oob_ptr = ptr + OUT_OF_BOUND_OFFSET;
+
+ TEST_VERIFY (samasan_get_size (ptr) == allocation_size);
+ /* the size of out-of-bound memory chunk should be zero */
+ TEST_VERIFY (samasan_get_size (oob_ptr) == 0);
+
+ samasan_free (ptr);
+
+ /* the size of freed chunk should be zero */
+ TEST_VERIFY (samasan_get_size (ptr) == 0);
+#undef OUT_OF_BOUND_OFFSET
+}
+
+static inline bool
+is_aligned (uintptr_t address)
+{
+ return (address % sizeof (size_t)) == 0;
+}
+
+static void
+test_aligned_allocation (void)
+{
+ const size_t allocation_size = 512;
+ void *ptr;
+
+ for (size_t i = 0; i < 100; i++)
+ {
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (is_aligned ((uintptr_t) ptr));
+ samasan_free(ptr);
+ }
+}
+
+static int
+do_test (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1/* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1/* replace */);
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ /* allocation tests */
+ test_allocations();
+ test_too_large_allocation ();
+ test_multiple_allocations ();
+ test_allocation_and_free ();
+ test_allocation_use_free_repeat ();
+
+ /* allocation sanity checking tests */
+ test_out_of_bound_pointer ();
+ test_allocated_size ();
+ test_wrong_get_size ();
+ test_aligned_allocation ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-block-sizes.c b/sampling-asan/tst-block-sizes.c
new file mode 100644
index 0000000000..5bf35ab7bc
--- /dev/null
+++ b/sampling-asan/tst-block-sizes.c
@@ -0,0 +1,68 @@
+/* Test and verify various chunk sizes in sampling-asan.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+static void
+test_multiple_chunk_sizes (size_t size)
+{
+ void *ptr;
+ char *cptr;
+ char chunk_size[10];
+ const size_t increase = 64;
+ size_t allocation_size = increase;
+
+ sprintf(chunk_size, "%ld", size);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", chunk_size, 1/* replace */);
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == true);
+ for (; allocation_size <= size; allocation_size += increase)
+ {
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr != NULL);
+ cptr = (char *) ptr;
+ *cptr = 'A';
+ samasan_free (ptr);
+ }
+ samasan_deinit ();
+}
+
+static int
+do_test (void)
+{
+ const size_t page_size = 4096;
+
+ setenv ("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1/* replace */);
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+
+ for (size_t i = 1; i < 10; i++)
+ test_multiple_chunk_sizes (page_size * i);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-chunk-pick.c b/sampling-asan/tst-chunk-pick.c
new file mode 100644
index 0000000000..94793e69d9
--- /dev/null
+++ b/sampling-asan/tst-chunk-pick.c
@@ -0,0 +1,103 @@
+/* Test and verify memory chunk pick styles defined in sampling-asan.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+#include "samasan_allocate.h" /* for memory_chunk_pick_style_t */
+
+static const size_t page_size = 4096;
+
+static bool
+check_allocation_align (memory_chunk_pick_style_t style, size_t size, void *ptr)
+{
+ uintptr_t address = (uintptr_t) ptr;
+ uintptr_t page_address = address - (address % page_size);
+
+ if (style == PICK_FROM_LEFT)
+ {
+ /* If style == PICK_FROM_LEFT, the address should be same to
+ * the address of the memory block. */
+ if (address == page_address)
+ return true;
+ return false;
+ }
+ else if (style == PICK_FROM_RIGHT)
+ {
+ /* If style == PICK_FROM_RIGHT, the end of the memory chunk should be
+ * same to the end of the memory block. */
+ if (address == (page_address + page_size - size))
+ return true;
+ return false;
+ }
+ else /* style == PICK_CENTER */
+ {
+ /* If style == PICK_CENTER, the address should be located at the
+ center of the memory block. */
+ uintptr_t expected = page_address + ((page_size - size) >> 1);
+ if (address == expected)
+ return true;
+ return false;
+ }
+ return false;
+}
+
+static void
+test_memory_chunk_pick_style (memory_chunk_pick_style_t style)
+{
+ const size_t alloc_size = 512;
+ void *ptr;
+
+ if (style == PICK_FROM_LEFT)
+ setenv ("SAMASAN_CHUNK_PICK", "LEFT", 1);
+ else if (style == PICK_FROM_RIGHT)
+ setenv ("SAMASAN_CHUNK_PICK", "RIGHT", 1);
+ else
+ setenv ("SAMASAN_CHUNK_PICK", "CENTER", 1);
+
+ samasan_init();
+
+ ptr = samasan_allocate (alloc_size);
+ TEST_VERIFY (ptr != NULL);
+ TEST_VERIFY (check_allocation_align (style, alloc_size, ptr));
+ samasan_free (ptr);
+
+ samasan_deinit ();
+}
+
+static int
+do_test (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1/* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1/* replace */);
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+
+ for (memory_chunk_pick_style_t style = PICK_FROM_LEFT; style < PICK_END; style++)
+ test_memory_chunk_pick_style (style);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-common.c b/sampling-asan/tst-common.c
new file mode 100644
index 0000000000..333ab9d8ab
--- /dev/null
+++ b/sampling-asan/tst-common.c
@@ -0,0 +1,88 @@
+/* Definition of common functions for testing.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+static bool
+check_report (const char *keyword, const char *report_path)
+{
+ if (access (report_path, F_OK) == 0)
+ {
+ bool check = false;
+ FILE *report = fopen (report_path, "r");
+ if (report != NULL)
+ {
+ char buf[255], *substr;
+ while (fscanf (report, "%s", buf) != EOF)
+ {
+ substr = strstr (buf, keyword);
+ if (substr != NULL && !strncmp (substr, keyword, strlen (keyword)))
+ {
+ check = true;
+ break;
+ }
+ memset (buf, 0, sizeof (buf));
+ }
+ fclose (report);
+ }
+ return (check == true);
+ }
+ return false;
+}
+
+static bool
+wait_error (pid_t child_pid)
+{
+ int status;
+ waitpid (child_pid, &status, 0);
+ return WIFSIGNALED (status) && (WTERMSIG (status) == SIGSEGV);
+}
+
+static void
+clean_up_report (const char *report_path)
+{
+ if (access (report_path, F_OK) == 0)
+ unlink (report_path);
+}
+
+static void
+test_bed (void (*error_func) (void), const char *keyword,
+ const char *report_path)
+{
+ pid_t child_pid;
+
+ clean_up_report (report_path);
+
+ child_pid = _Fork();
+ TEST_VERIFY_EXIT (child_pid != -1);
+
+ if (child_pid == 0)
+ error_func ();
+ else
+ {
+ TEST_VERIFY_EXIT (wait_error (child_pid) == true);
+ TEST_VERIFY (check_report (keyword, report_path) == true);
+ }
+
+ clean_up_report (report_path);
+}
diff --git a/sampling-asan/tst-double-free.c b/sampling-asan/tst-double-free.c
new file mode 100644
index 0000000000..4ef5f5a62c
--- /dev/null
+++ b/sampling-asan/tst-double-free.c
@@ -0,0 +1,63 @@
+/* Test and verify a double-free case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_double_free (void)
+{
+ const size_t allocation_size = 512;
+ void *ptr;
+
+ ptr = samasan_allocate (allocation_size);
+ samasan_free (ptr);
+ samasan_free (ptr); /* raise segmentation fault */
+}
+
+static void test_double_free (const char *report_path)
+{
+ test_bed (do_double_free, "DOUBLE_FREE", report_path);
+}
+
+static int do_test (void)
+{
+ const char *report_path = "/tmp/double-free-error-report";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_double_free (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-init.c b/sampling-asan/tst-init.c
new file mode 100644
index 0000000000..45cafd3d69
--- /dev/null
+++ b/sampling-asan/tst-init.c
@@ -0,0 +1,120 @@
+/* Test and verify initialization in sampling-asan
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h"
+
+static void
+test_repeated_init_and_deinit (void)
+{
+#define REPEATS 100
+ setenv("SAMASAN_ENABLE", "true", 1/* replace */);
+
+ for (int i = 0; i < REPEATS; i++)
+ {
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == true);
+ samasan_deinit ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+ }
+#undef REPEATS
+}
+
+static void
+test_misconfigurations (void)
+{
+ setenv ("SAMASAN_ENABLE",
+ "truth" /* should be "yes" or "true" or "enable" or "on" */,
+ 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096" /* exceed the upper limit */,
+ 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "409600" /* exceed the upper limit */,
+ 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS",
+ "100000" /* exceed the upper limit */, 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.2" /* exceed 100% */, 1 /* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+}
+
+static void
+test_multiple_inits (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096" /* exceed the upper limit */,
+ 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == true);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == true);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled () == true);
+
+ samasan_deinit ();
+ TEST_VERIFY (samasan_is_enabled () == false);
+}
+
+static int
+do_test (void)
+{
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+
+ test_repeated_init_and_deinit ();
+ test_misconfigurations ();
+ test_multiple_inits ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-invalid-access.c b/sampling-asan/tst-invalid-access.c
new file mode 100644
index 0000000000..2105b068d2
--- /dev/null
+++ b/sampling-asan/tst-invalid-access.c
@@ -0,0 +1,71 @@
+/* Test and verify an invalid-access case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_invalid_access (void)
+{
+ const size_t allocation_size = 512;
+ void *ptr;
+ char *cptr;
+
+ ptr = samasan_allocate (allocation_size);
+ /* The sampling memory pool tends to allocate a memory chunk from
+ the tail of the memory pool for the first allocation. Because of
+ that, an access to the increased address from the pointer causes
+ an undefined behavior since it reaches beyond the memory pool.
+ So, just use the decreased address for here. */
+ cptr = (char *) ptr - 4096 * 2; // One page for partition
+ *cptr = 'A'; /* an invalid access occurred! */
+}
+
+static void
+test_invalid_access (const char *report_path)
+{
+ test_bed (do_invalid_access, "INVALID_ACCESS", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/invalid-access-error-report";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_invalid_access (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-invalid-access2.c b/sampling-asan/tst-invalid-access2.c
new file mode 100644
index 0000000000..64cb34c643
--- /dev/null
+++ b/sampling-asan/tst-invalid-access2.c
@@ -0,0 +1,66 @@
+/* Test and verify an unaligned-access case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_invalid_access (void)
+{
+ const size_t allocation_size = 512;
+ void *ptr;
+ char *cptr;
+
+ ptr = samasan_allocate (allocation_size);
+ cptr = (char *) ptr + 4096;
+ *cptr = 'A'; /* an invalid access occurred! */
+}
+
+static void
+test_invalid_access (const char *report_path)
+{
+ test_bed (do_invalid_access, "INVALID_ACCESS", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/invalid-access-error-report2";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "12288", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_invalid_access (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-invalid-free.c b/sampling-asan/tst-invalid-free.c
new file mode 100644
index 0000000000..e4a5af4209
--- /dev/null
+++ b/sampling-asan/tst-invalid-free.c
@@ -0,0 +1,65 @@
+/* Test and verify an invalid-free case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_invalid_free (void)
+{
+ void *ptr;
+ const size_t allocation_size = 512;
+
+ ptr = samasan_allocate (allocation_size);
+ ptr += 512;
+ samasan_free (ptr); /* invalid free error occurred */
+}
+
+static void
+test_invalid_free (const char *report_path)
+{
+ test_bed (do_invalid_free, "INVALID_FREE", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/invalid-free-error-report";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_invalid_free (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-invalid-free2.c b/sampling-asan/tst-invalid-free2.c
new file mode 100644
index 0000000000..7ad911ec24
--- /dev/null
+++ b/sampling-asan/tst-invalid-free2.c
@@ -0,0 +1,65 @@
+/* Test and verify an invalid-free case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_invalid_free (void)
+{
+ void *ptr;
+ const size_t allocation_size = 512;
+
+ ptr = samasan_allocate (allocation_size);
+ ptr -= 512;
+ samasan_free (ptr); /* invalid free error occurred */
+}
+
+static void
+test_invalid_free (const char *report_path)
+{
+ test_bed (do_invalid_free, "INVALID_FREE", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/invalid-free-error-report2";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_invalid_free (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-invalid-write.c b/sampling-asan/tst-invalid-write.c
new file mode 100644
index 0000000000..0e3632020f
--- /dev/null
+++ b/sampling-asan/tst-invalid-write.c
@@ -0,0 +1,69 @@
+/* Test and verify allocations in sampling-asan.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_invalid_write (void)
+{
+ size_t allocation_size = 512;
+ void *ptr;
+ char *cptr;
+
+ ptr = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr != NULL);
+ cptr = (char *) ptr;
+ *(cptr + allocation_size) = 'a';
+ samasan_free (ptr); /* error occurred! */
+}
+
+static void
+test_invalid_write (const char *report_path)
+{
+ test_bed (do_invalid_write, "INVALID_WRITE", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/invalid-write-error-report";
+ setenv ("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "8192", 1/* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1/* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1/* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ /* invalid-write tests */
+ test_invalid_write (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-out-of-memory-pool.c b/sampling-asan/tst-out-of-memory-pool.c
new file mode 100644
index 0000000000..cdf89533f7
--- /dev/null
+++ b/sampling-asan/tst-out-of-memory-pool.c
@@ -0,0 +1,61 @@
+/* Test and verify an out-of-memory-pool case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_out_of_memory_pool (void)
+{
+ char *cptr = (char *) 0;
+ *cptr = 'A'; /* an out-of-memory-pool fault occurred! */
+}
+
+static void
+test_out_of_memory_pool (const char *report_path)
+{
+ test_bed (do_out_of_memory_pool, "OUT_OF_MEMORY_POOL", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/out-of-memory-pool-error-report";
+
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "1", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1 /* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_out_of_memory_pool (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-partition-sizes.c b/sampling-asan/tst-partition-sizes.c
new file mode 100644
index 0000000000..78cdaadaea
--- /dev/null
+++ b/sampling-asan/tst-partition-sizes.c
@@ -0,0 +1,88 @@
+/* Test and verify configurable partition size in sampling-asan
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "samasan.h"
+#include "samasan_init.h"
+
+static void
+test_partition_size (size_t partition_size)
+{
+ char buf[100];
+ const size_t allocation_size = 512;
+ void *ptr[10];
+ char *cptr;
+
+ sprintf (buf, "%ld", partition_size);
+ setenv("SAMASAN_PARTITION_SIZE", buf, 1/* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (samasan_is_enabled());
+ for (size_t i = 0; i < 10; i++)
+ {
+ ptr[i] = samasan_allocate (allocation_size);
+ TEST_VERIFY (ptr[i] != NULL);
+ cptr = (char *) ptr[i];
+ memset (cptr, 'A' + i, allocation_size);
+ }
+ for (size_t i = 0; i < 10; i++)
+ samasan_free (ptr[i]);
+ samasan_deinit();
+}
+
+static void
+test_wrong_partition_size (size_t partition_size)
+{
+ char buf[100];
+
+ sprintf (buf, "%ld", partition_size);
+ setenv("SAMASAN_PARTITION_SIZE", buf, 1/* replace */);
+
+ samasan_init ();
+ TEST_VERIFY (!samasan_is_enabled());
+}
+
+static int
+do_test (void)
+{
+ const size_t page_size = 4096;
+
+ setenv("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv("SAMASAN_MAX_ALLOC_SIZE", "4096", 1/* replace */);
+ setenv("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1/* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit();
+
+ for (size_t i = 0; i <= 10; i++)
+ test_partition_size (page_size * i);
+
+ test_wrong_partition_size (-1);
+ test_wrong_partition_size (page_size * 11);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-pause-on-fork.c b/sampling-asan/tst-pause-on-fork.c
new file mode 100644
index 0000000000..995f0914e5
--- /dev/null
+++ b/sampling-asan/tst-pause-on-fork.c
@@ -0,0 +1,139 @@
+/* Test and verify the pause-on-fork feature.
+ This is implemented by pthread_atfork (internally, __register_atfork).
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+static bool thread_ready = false;
+static pthread_mutex_t mutex;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static inline void
+thread_get_ready (void)
+{
+ xpthread_mutex_lock (&mutex);
+ thread_ready = true;
+ xpthread_cond_signal (&cond);
+ xpthread_mutex_unlock (&mutex);
+}
+
+static void*
+memory_pool_stay_pause (void* dummy)
+{
+ thread_get_ready ();
+ return NULL;
+}
+
+static void*
+memory_pool_enable (void* dummy)
+{
+ thread_get_ready ();
+ sleep (1);
+ samasan_memory_pool_resume ();
+ return NULL;
+}
+
+static void
+test_pthread_fork (bool memory_pool_resume)
+{
+ pid_t pid;
+ pthread_t thread_id;
+
+ if (memory_pool_resume)
+ thread_id = xpthread_create (NULL, &memory_pool_enable, NULL);
+ else
+ thread_id = xpthread_create (NULL, &memory_pool_stay_pause, NULL);
+
+ xpthread_mutex_lock (&mutex);
+ while (!thread_ready)
+ xpthread_cond_wait (&cond, &mutex);
+ xpthread_mutex_unlock (&mutex);
+
+ if (!memory_pool_resume)
+ alarm (1);
+ samasan_memory_pool_pause ();
+ pid = fork ();
+
+ if (pid == 0)
+ _exit (0);
+
+ /* If memory_pool_enable == false, never reached here.
+ The process will be terminated by the alarm call. */
+ waitpid (pid, NULL, 0);
+ xpthread_join (thread_id);
+}
+
+static void
+test_bed (bool memory_pool_resume)
+{
+ pid_t pid;
+ int ret;
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ xpthread_mutex_init (&mutex, NULL);
+ thread_ready = false;
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ test_pthread_fork (memory_pool_resume);
+ _exit (0);
+ }
+
+ waitpid (pid, &ret, 0);
+ if (memory_pool_resume)
+ {
+ TEST_VERIFY (WIFEXITED (ret));
+ TEST_COMPARE (WTERMSIG (ret), 0);
+ }
+ else
+ {
+ TEST_VERIFY (WIFSIGNALED (ret));
+ TEST_COMPARE (WTERMSIG (ret), SIGALRM);
+ }
+}
+
+static int
+do_test (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ setenv ("SAMASAN_PAUSE_ON_FORK", "true", 1 /* replace */);
+
+ test_bed (false /* memory_pool_resume */);
+ test_bed (true /* memory_pool_resume */);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-sampling.c b/sampling-asan/tst-sampling.c
new file mode 100644
index 0000000000..981903469d
--- /dev/null
+++ b/sampling-asan/tst-sampling.c
@@ -0,0 +1,82 @@
+/* Test and verify sampling methods in sampling-asan
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+static void
+test_sampling_on_uninited (void)
+{
+ const size_t allocation_size = 512;
+
+ TEST_VERIFY (samasan_sampling_ok (allocation_size) == false);
+}
+
+static void
+test_sampling (void)
+{
+ const size_t allocation_size = 512;
+ const size_t large_allocation_size = 4097;
+
+ TEST_VERIFY (samasan_sampling_ok (allocation_size) == true);
+ TEST_VERIFY (samasan_sampling_ok (large_allocation_size) == false);
+}
+
+static void
+test_sampling_exhausted (void)
+{
+#define MAX_ALLOCATIONS 10
+ const size_t allocation_size = 512;
+ void *ptr[MAX_ALLOCATIONS] = {NULL,};
+
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ ptr[i] = samasan_allocate (allocation_size);
+ TEST_VERIFY (samasan_sampling_ok (allocation_size) == false);
+
+ for (int i = 0; i < MAX_ALLOCATIONS; i++)
+ samasan_free (ptr[i]);
+ TEST_VERIFY (samasan_sampling_ok (allocation_size) == true);
+#undef MAX_ALLOCATIONS
+}
+
+static int
+do_test (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ test_sampling_on_uninited ();
+
+ samasan_init ();
+
+ test_sampling ();
+ test_sampling_exhausted ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-threaded-allocation.c b/sampling-asan/tst-threaded-allocation.c
new file mode 100644
index 0000000000..c75581ab5b
--- /dev/null
+++ b/sampling-asan/tst-threaded-allocation.c
@@ -0,0 +1,90 @@
+/* Test and verify threaded-allocations in sampling-asan
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#define MAX_ON_GOING_ALLOCATIONS 100
+#define MAX_THREADS 10
+static int allocations_per_thread = MAX_ON_GOING_ALLOCATIONS / MAX_THREADS;
+static int thread_id;
+static void *global_ptr[MAX_ON_GOING_ALLOCATIONS] = { NULL, };
+
+static void *
+allocation_thread_func (void *data)
+{
+ int id = __atomic_fetch_add (&thread_id, 1, __ATOMIC_SEQ_CST);
+
+ for (int i = 0; i < allocations_per_thread; i++)
+ {
+ global_ptr[id * MAX_THREADS + i] = samasan_allocate (sizeof (int));
+ TEST_VERIFY (global_ptr[id * MAX_THREADS + i] != NULL);
+ }
+
+ return NULL;
+}
+
+static void
+test_multi_threaded_allocation (void)
+{
+ pthread_t *threads = xcalloc (sizeof (pthread_t), MAX_THREADS);
+ void *ptr;
+
+ thread_id = 0;
+
+ for (int i = 0; i < MAX_THREADS; i++)
+ threads[i] = xpthread_create (NULL, allocation_thread_func, NULL);
+
+ for (int i = 0; i < MAX_THREADS; i++)
+ xpthread_join (threads[i]);
+ ptr = samasan_allocate (sizeof (int));
+ TEST_VERIFY (ptr == NULL);
+
+ for (int i = 0; i < MAX_ON_GOING_ALLOCATIONS; i++)
+ {
+ samasan_free (global_ptr[i]);
+ global_ptr[i] = NULL;
+ }
+ free (threads);
+}
+
+static int
+do_test (void)
+{
+ setenv ("SAMASAN_ENABLE", "true", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1 /* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "100", 1 /* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1 /* replace */);
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_multi_threaded_allocation ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sampling-asan/tst-use-after-free.c b/sampling-asan/tst-use-after-free.c
new file mode 100644
index 0000000000..96e5b0c377
--- /dev/null
+++ b/sampling-asan/tst-use-after-free.c
@@ -0,0 +1,66 @@
+/* Test and verify a double-free case.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/support.h>
+#include <stdlib.h>
+
+#include "samasan.h"
+#include "samasan_init.h" /* for samasan_deinit */
+
+#include "tst-common.c"
+
+static void
+do_use_after_free (void)
+{
+ size_t allocation_size = 512;
+ int *ptr;
+
+ ptr = (int *) samasan_allocate (allocation_size);
+ *(ptr) = 1;
+ samasan_free (ptr);
+ *(ptr) = 0; /* raise use-after-free */
+}
+
+static void
+test_use_after_free (const char *report_path)
+{
+ test_bed (do_use_after_free, "USE_AFTER_FREE", report_path);
+}
+
+static int
+do_test (void)
+{
+ const char *report_path = "/tmp/use-after-free-error-report";
+
+ setenv ("SAMASAN_ENABLE", "true", 1/* replace */);
+ setenv ("SAMASAN_MAX_ALLOC_SIZE", "4096", 1/* replace */);
+ setenv ("SAMASAN_MAX_ON_GOING_ALLOCATIONS", "10", 1/* replace */);
+ setenv ("SAMASAN_SAMPLING_RATE", "1.0", 1/* replace */);
+ setenv ("SAMASAN_OUTPUT_PATH", report_path, 1/* replace */);
+
+ /* glibc already initialized sampling-asan.
+ So, deinitialize sampling-asan before starting the test */
+ samasan_deinit ();
+ samasan_init ();
+
+ test_use_after_free (report_path);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.25.1
More information about the Libc-alpha
mailing list