Mark Wielaard aa7617
commit 5fdabb72fdcba6bcf788eaa19c1ee557c13b8a7a
Mark Wielaard aa7617
Author: Mark Wielaard <mark@klomp.org>
Mark Wielaard aa7617
Date:   Sat Dec 1 23:54:40 2018 +0100
Mark Wielaard aa7617
Mark Wielaard aa7617
    Bug 401627 - Add wcsncmp override and testcase.
Mark Wielaard aa7617
    
Mark Wielaard aa7617
    glibc 2.28 added an avx2 optimized variant of wstrncmp which memcheck
Mark Wielaard aa7617
    cannot proof correct. Add a simple override in vg_replace_strmem.c.
Mark Wielaard aa7617
Mark Wielaard aa7617
diff --git a/memcheck/tests/wcs.c b/memcheck/tests/wcs.c
Mark Wielaard aa7617
index 15730ad..538304b 100644
Mark Wielaard aa7617
--- a/memcheck/tests/wcs.c
Mark Wielaard aa7617
+++ b/memcheck/tests/wcs.c
Mark Wielaard aa7617
@@ -1,5 +1,6 @@
Mark Wielaard aa7617
-// Uses various wchar_t * functions that have hand written SSE assembly
Mark Wielaard aa7617
-// implementations in glibc. wcslen, wcscpy, wcscmp, wcsrchr, wcschr.
Mark Wielaard aa7617
+// Uses various wchar_t * functions that have hand written SSE and/or AVX2
Mark Wielaard aa7617
+// assembly implementations in glibc.
Mark Wielaard aa7617
+// wcslen, wcscpy, wcscmp, wcsncmp, wcsrchr, wcschr.
Mark Wielaard aa7617
 
Mark Wielaard aa7617
 #include <stdio.h>
Mark Wielaard aa7617
 #include <stdlib.h>
Mark Wielaard aa7617
@@ -18,6 +19,8 @@ int main(int argc, char **argv)
Mark Wielaard aa7617
   c = wcscpy (b, a);
Mark Wielaard aa7617
 
Mark Wielaard aa7617
   fprintf (stderr, "wcscmp equal: %d\n", wcscmp (a, b)); // wcscmp equal: 0
Mark Wielaard aa7617
+  fprintf (stderr,
Mark Wielaard aa7617
+	   "wcsncmp equal: %d\n", wcsncmp (a, b, l)); // wcsncmp equal: 0
Mark Wielaard aa7617
 
Mark Wielaard aa7617
   d = wcsrchr (a, L'd');
Mark Wielaard aa7617
   e = wcschr (a, L'd');
Mark Wielaard aa7617
diff --git a/memcheck/tests/wcs.stderr.exp b/memcheck/tests/wcs.stderr.exp
Mark Wielaard aa7617
index 41d74c8..d5b5959 100644
Mark Wielaard aa7617
--- a/memcheck/tests/wcs.stderr.exp
Mark Wielaard aa7617
+++ b/memcheck/tests/wcs.stderr.exp
Mark Wielaard aa7617
@@ -1,3 +1,4 @@
Mark Wielaard aa7617
 wcslen: 53
Mark Wielaard aa7617
 wcscmp equal: 0
Mark Wielaard aa7617
+wcsncmp equal: 0
Mark Wielaard aa7617
 wcsrchr == wcschr: 1
Mark Wielaard aa7617
diff --git a/shared/vg_replace_strmem.c b/shared/vg_replace_strmem.c
Mark Wielaard aa7617
index d6927f0..89a7dcc 100644
Mark Wielaard aa7617
--- a/shared/vg_replace_strmem.c
Mark Wielaard aa7617
+++ b/shared/vg_replace_strmem.c
Mark Wielaard aa7617
@@ -103,6 +103,7 @@
Mark Wielaard aa7617
    20420 STPNCPY
Mark Wielaard aa7617
    20430 WMEMCHR
Mark Wielaard aa7617
    20440 WCSNLEN
Mark Wielaard aa7617
+   20450 WSTRNCMP
Mark Wielaard aa7617
 */
Mark Wielaard aa7617
 
Mark Wielaard aa7617
 #if defined(VGO_solaris)
Mark Wielaard aa7617
@@ -1927,6 +1928,36 @@ static inline void my_exit ( int x )
Mark Wielaard aa7617
  WCSCMP(VG_Z_LIBC_SONAME,          wcscmp)
Mark Wielaard aa7617
 #endif
Mark Wielaard aa7617
 
Mark Wielaard aa7617
+/*---------------------- wcsncmp ----------------------*/
Mark Wielaard aa7617
+
Mark Wielaard aa7617
+// This is a wchar_t equivalent to strncmp.  We don't
Mark Wielaard aa7617
+// have wchar_t available here, but in the GNU C Library
Mark Wielaard aa7617
+// wchar_t is always 32 bits wide and wcsncmp uses signed
Mark Wielaard aa7617
+// comparison, not unsigned as in strncmp function.
Mark Wielaard aa7617
+
Mark Wielaard aa7617
+#define WCSNCMP(soname, fnname) \
Mark Wielaard aa7617
+   int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
Mark Wielaard aa7617
+          ( const Int* s1, const Int* s2, SizeT nmax ); \
Mark Wielaard aa7617
+   int VG_REPLACE_FUNCTION_EZU(20450,soname,fnname) \
Mark Wielaard aa7617
+          ( const Int* s1, const Int* s2, SizeT nmax ) \
Mark Wielaard aa7617
+   { \
Mark Wielaard aa7617
+      SizeT n = 0; \
Mark Wielaard aa7617
+      while (True) { \
Mark Wielaard aa7617
+         if (n >= nmax) return 0; \
Mark Wielaard aa7617
+         if (*s1 == 0 && *s2 == 0) return 0; \
Mark Wielaard aa7617
+         if (*s1 == 0) return -1; \
Mark Wielaard aa7617
+         if (*s2 == 0) return 1; \
Mark Wielaard aa7617
+         \
Mark Wielaard aa7617
+         if (*s1 < *s2) return -1; \
Mark Wielaard aa7617
+         if (*s1 > *s2) return 1; \
Mark Wielaard aa7617
+         \
Mark Wielaard aa7617
+         s1++; s2++; n++; \
Mark Wielaard aa7617
+      } \
Mark Wielaard aa7617
+   }
Mark Wielaard aa7617
+#if defined(VGO_linux)
Mark Wielaard aa7617
+ WCSNCMP(VG_Z_LIBC_SONAME,          wcsncmp)
Mark Wielaard aa7617
+#endif
Mark Wielaard aa7617
+
Mark Wielaard aa7617
 /*---------------------- wcscpy ----------------------*/
Mark Wielaard aa7617
 
Mark Wielaard aa7617
 // This is a wchar_t equivalent to strcpy.  We don't