[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