Blob Blame History Raw
From 42ca1c480a5bca408a54c6a24d2be2c081d121ac Mon Sep 17 00:00:00 2001
From: Andreas Arnez <arnez@linux.ibm.com>
Date: Thu, 19 May 2022 13:54:06 +0200
Subject: [PATCH] Bug 454040 - Add intercept for memmem on s390x

Since memcheck may report false positives in an optimized version of memmem on
s390x, add an intercept for memmem on s390x platforms.
---
 shared/vg_replace_strmem.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/shared/vg_replace_strmem.c b/shared/vg_replace_strmem.c
index 5396e83be..d28e74206 100644
--- a/shared/vg_replace_strmem.c
+++ b/shared/vg_replace_strmem.c
@@ -103,6 +103,7 @@
    20430 WMEMCHR
    20440 WCSNLEN
    20450 WSTRNCMP
+   20460 MEMMEM
 */
 
 #if defined(VGO_solaris)
@@ -1785,6 +1786,41 @@ static inline void my_exit ( int x )
 
 #endif
 
+/*---------------------- memmem ----------------------*/
+
+#define MEMMEM(soname, fnname) \
+   void* VG_REPLACE_FUNCTION_EZU(20460,soname,fnname) \
+         (const void* haystack, SizeT hlen, const void* needle, SizeT nlen); \
+   void* VG_REPLACE_FUNCTION_EZU(20460,soname,fnname) \
+         (const void* haystack, SizeT hlen, const void* needle, SizeT nlen) \
+   { \
+      const HChar* h = haystack; \
+      const HChar* n = needle; \
+      \
+      /* If the needle is the empty string, match immediately. */ \
+      if (nlen == 0) return CONST_CAST(void *,h); \
+      \
+      HChar n0 = n[0]; \
+      \
+      for (; hlen >= nlen; hlen--, h++) { \
+         if (h[0] != n0) continue; \
+         \
+         UWord i; \
+         for (i = 1; i < nlen; i++) { \
+            if (n[i] != h[i]) \
+               break; \
+         } \
+         if (i == nlen) \
+           return CONST_CAST(HChar *,h); \
+         \
+      } \
+      return NULL; \
+   }
+
+#if defined(VGP_s390x_linux)
+ MEMMEM(VG_Z_LIBC_SONAME,          memmem)
+#endif
+
 
 /*---------------------- strpbrk ----------------------*/
 
-- 
2.31.1

From 4d675f309bcd2d4e9e2b9e6f4aba30f85116bb9b Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Thu, 19 May 2022 18:08:40 -0400
Subject: [PATCH] Add memmem memcheck tests

---
 memcheck/tests/Makefile.am       |  3 ++
 memcheck/tests/filter_memmem     |  5 ++
 memcheck/tests/memmem.c          | 81 ++++++++++++++++++++++++++++++++
 memcheck/tests/memmem.stderr.exp |  2 +
 memcheck/tests/memmem.vgtest     |  3 ++
 5 files changed, 94 insertions(+)
 create mode 100755 memcheck/tests/filter_memmem
 create mode 100644 memcheck/tests/memmem.c
 create mode 100644 memcheck/tests/memmem.stderr.exp
 create mode 100644 memcheck/tests/memmem.vgtest

diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index eb9487272..4d181c1ac 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -79,6 +79,7 @@ dist_noinst_SCRIPTS = \
 	filter_strchr \
 	filter_varinfo3 \
 	filter_memcheck \
+	filter_memmem \
 	filter_overlaperror \
 	filter_malloc_free \
         filter_sized_delete
@@ -220,6 +221,7 @@ EXTRA_DIST = \
 	memalign2.stderr.exp memalign2.vgtest \
 	memcmptest.stderr.exp memcmptest.stderr.exp2 \
 	memcmptest.stdout.exp memcmptest.vgtest \
+	memmem.stderr.exp memmem.vgtest \
 	mempool.stderr.exp mempool.vgtest \
 	mempool2.stderr.exp mempool2.vgtest \
 	metadata.stderr.exp metadata.stdout.exp metadata.vgtest \
@@ -417,6 +419,7 @@ check_PROGRAMS = \
 	malloc_usable malloc1 malloc2 malloc3 manuel1 manuel2 manuel3 \
 	match-overrun \
 	memalign_test memalign2 memcmptest mempool mempool2 mmaptest \
+	memmem \
 	mismatches new_override metadata \
 	nanoleak_supp nanoleak2 new_nothrow \
 	noisy_child \
diff --git a/memcheck/tests/filter_memmem b/memcheck/tests/filter_memmem
new file mode 100755
index 000000000..f4a40b2d1
--- /dev/null
+++ b/memcheck/tests/filter_memmem
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+# Too many memmem implementations and overrides.
+# So just keep the main file lines.
+./filter_stderr "$@" | grep " main (memmem.c:"
diff --git a/memcheck/tests/memmem.c b/memcheck/tests/memmem.c
new file mode 100644
index 000000000..d627076e3
--- /dev/null
+++ b/memcheck/tests/memmem.c
@@ -0,0 +1,81 @@
+#define _GNU_SOURCE
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* mallocs an mem block and fills it with A. A needs to be a zero
+   terminated string. The A string chars, minus the terminating zero
+   are copied into the returned mem block.  */
+static void *
+create_mem (const char *a)
+{
+  size_t len = strlen (a);
+  void *mem = malloc (len);
+  memcpy (mem, a, len);
+  return mem;
+}
+
+int
+main ()
+{
+  char *haystack;
+  char *needle;
+
+  haystack = create_mem ("a");
+  needle = create_mem ("a");
+  assert (memmem (haystack, 0, needle, 0) == haystack);
+  assert (memmem (haystack, 1, needle, 0) == haystack);
+  assert (memmem (haystack, 0, needle, 1) == NULL);
+  assert (memmem (haystack, 1, needle, 1) == haystack);
+  free (haystack);
+  free (needle);
+
+  haystack = create_mem ("abc");
+  needle = create_mem ("bc");
+  assert (memmem (haystack, 3, needle, 0) == haystack);
+  assert (memmem (haystack, 3, needle, 2) == haystack + 1);
+  assert (memmem (haystack + 1, 2, needle, 2) == haystack + 1);
+  assert (memmem (haystack + 2, 1, needle, 2) == NULL);
+  free (haystack);
+  free (needle);
+
+  haystack = create_mem ("abcabcabc");
+  needle = create_mem ("bca");
+  assert (memmem (haystack, 9, needle, 3) == haystack + 1);
+  free (haystack);
+  free (needle);
+
+  haystack = create_mem ("abcabcabc");
+  needle = create_mem ("bcad");
+  assert (memmem (haystack, 9, needle, 4) == NULL);
+  free (haystack);
+  free (needle);
+
+  haystack = create_mem ("xxxxxxxxxxxxxxxxxABC");
+  needle = create_mem ("ABCD");
+  assert (memmem (haystack, 20, needle, 2) == haystack + 17);
+  assert (memmem (haystack + 3, 17, needle, 2) == haystack + 17);
+  assert (memmem (haystack + 15, 5, needle, 2) == haystack + 17);
+  assert (memmem (haystack, 20, needle, 3) == haystack + 17);
+  assert (memmem (haystack + 3, 17, needle, 3) == haystack + 17);
+  assert (memmem (haystack + 15, 5, needle, 3) == haystack + 17);
+  assert (memmem (haystack, 20, needle, 4) == NULL);
+  assert (memmem (haystack + 3, 5, needle, 4) == NULL);
+  assert (memmem (haystack + 15, 5, needle, 4) == NULL);
+  free (haystack);
+  free (needle);
+
+  haystack = malloc (1);
+  needle = create_mem ("a");
+  assert (memmem (haystack, 1, needle, 1) == NULL);
+  free (haystack);
+  free (needle);
+
+  haystack = create_mem ("A");
+  needle = malloc (1);
+  assert (memmem (haystack, 1, needle, 1) == NULL);
+  free (haystack);
+  free (needle);
+
+  return 0;
+}
diff --git a/memcheck/tests/memmem.stderr.exp b/memcheck/tests/memmem.stderr.exp
new file mode 100644
index 000000000..b4612fbd4
--- /dev/null
+++ b/memcheck/tests/memmem.stderr.exp
@@ -0,0 +1,2 @@
+   by 0x........: main (memmem.c:70)
+   by 0x........: main (memmem.c:76)
diff --git a/memcheck/tests/memmem.vgtest b/memcheck/tests/memmem.vgtest
new file mode 100644
index 000000000..6d12895df
--- /dev/null
+++ b/memcheck/tests/memmem.vgtest
@@ -0,0 +1,3 @@
+prog: memmem
+vgopts: -q
+stderr_filter: filter_memmem
-- 
2.18.4