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