From: Paul Floyd Date: Mon, 16 Oct 2023 21:14:39 +0000 (+0200) Subject: Bug 475652 - Missing suppression for __wcsncpy_avx2 (strncpy-avx2.S:308)? X-Git-Tag: VALGRIND_3_22_0~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7829b6d4783f94fce6ea3323fb13d21ff025913;p=thirdparty%2Fvalgrind.git Bug 475652 - Missing suppression for __wcsncpy_avx2 (strncpy-avx2.S:308)? Adds a replace strmem wrapper for wcsncpy Whilst doing this I noticed that memcheck/tests/filter_memcheck wasn't filtering memcheck/tests/freebsd/timingsafe properly. That's because before filtering vg_replace_strmem.c and vg_replace_malloc.c there's a check that the test exe filename does not match the line. In this case the test exe was "timingsafe", but line contained "timingsafe_memcmp", which matched leaving vg_replace_strmem.c unfiltered. So I just renamed the testcase. --- diff --git a/.gitignore b/.gitignore index 68f3a83762..e017762144 100644 --- a/.gitignore +++ b/.gitignore @@ -1016,6 +1016,7 @@ /memcheck/tests/wcs /memcheck/tests/weirdioctl /memcheck/tests/with space +/memcheck/tests/wcsncpy /memcheck/tests/wmemcmp /memcheck/tests/wrap1 /memcheck/tests/wrap2 @@ -1393,7 +1394,7 @@ /memcheck/tests/freebsd/statfs /memcheck/tests/freebsd/static_allocs /memcheck/tests/freebsd/timerfd -/memcheck/tests/freebsd/timingsafe +/memcheck/tests/freebsd/timing_safe /memcheck/tests/freebsd/utimens /memcheck/tests/freebsd/utimes diff --git a/NEWS b/NEWS index b2a385d8df..cd73fa47d1 100644 --- a/NEWS +++ b/NEWS @@ -87,6 +87,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 473944 Handle mold linker split RW PT_LOAD segments correctly 474332 aligned_alloc under Valgrind returns nullptr when alignment is not a multiple of sizeof(void *) 475650 DRD does not work with C11 threads +475652 Missing suppression for __wcsncpy_avx2 (strncpy-avx2.S:308)? n-i-bz Allow arguments with spaces in .valgrindrc files n-i-bz FreeBSD fixed reading of Valgrind tools own debuginfo diff --git a/configure.ac b/configure.ac index 357e6588fd..a35b9aa301 100755 --- a/configure.ac +++ b/configure.ac @@ -4913,7 +4913,8 @@ AC_CHECK_FUNCS([ \ strchrnul \ memrchr \ strndup \ - close_range + close_range \ + wcsncpy ]) # AC_CHECK_LIB adds any library found to the variable LIBS, and links these @@ -4943,6 +4944,8 @@ AM_CONDITIONAL([HAVE_GETADDRINFO], [test x$ac_cv_func_getaddrinfo = xyes]) AM_CONDITIONAL([HAVE_CLOSE_RANGE], [test x$ac_cv_func_close_range = xyes]) +AM_CONDITIONAL([HAVE_WCSNCPY], + [test x$ac_cv_func_wcsncpy = xyes]) if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \ diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 12d9595668..87ae8d94e6 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -423,6 +423,7 @@ EXTRA_DIST = \ vcpu_fnfns.stdout.exp-darwin vcpu_fnfns.stdout.exp-solaris \ vcpu_fnfns.stderr.exp vcpu_fnfns.vgtest \ wcs.vgtest wcs.stderr.exp wcs.stdout.exp \ + wcsncpy.vgtest wcsncpy.stderr.exp \ wmemcmp.vgtest wmemcmp.stderr.exp \ wrap1.vgtest wrap1.stdout.exp wrap1.stderr.exp \ wrap2.vgtest wrap2.stdout.exp wrap2.stderr.exp \ @@ -581,6 +582,11 @@ if HAVE_PTHREAD_SETNAME_NP check_PROGRAMS += threadname endif +# are there still pre-C99 C compilers? +if HAVE_WCSNCPY +check_PROGRAMS += wcsncpy +endif + AM_CFLAGS += $(AM_FLAG_M3264_PRI) AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index 23298e9ecd..0e45aeab61 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -121,8 +121,8 @@ EXTRA_DIST = \ timerfd.vgtest \ timerfd.stderr.exp \ timerfd.stdout.exp \ - timingsafe.vgtest \ - timingsafe.stderr.exp \ + timing_safe.vgtest \ + timing_safe.stderr.exp \ utimens.vgtest \ utimens.stderr.exp \ utimes.vgtest \ @@ -148,7 +148,7 @@ check_PROGRAMS = \ stat \ statfs \ static_allocs \ - timingsafe \ + timing_safe \ utimens \ utimes diff --git a/memcheck/tests/freebsd/timingsafe.c b/memcheck/tests/freebsd/timing_safe.c similarity index 100% rename from memcheck/tests/freebsd/timingsafe.c rename to memcheck/tests/freebsd/timing_safe.c diff --git a/memcheck/tests/freebsd/timing_safe.stderr.exp b/memcheck/tests/freebsd/timing_safe.stderr.exp new file mode 100644 index 0000000000..f1aa70e03f --- /dev/null +++ b/memcheck/tests/freebsd/timing_safe.stderr.exp @@ -0,0 +1,54 @@ +Conditional jump or move depends on uninitialised value(s) + at 0x........: timingsafe_bcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:30) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: timingsafe_bcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:30) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: timingsafe_memcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:31) + +Conditional jump or move depends on uninitialised value(s) + at 0x........: timingsafe_memcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:31) + +Invalid read of size 1 + at 0x........: timingsafe_bcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:35) + Address 0x........ is 0 bytes after a block of size 12 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + by 0x........: main (timing_safe.c:33) + +Invalid read of size 1 + at 0x........: timingsafe_memcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:36) + Address 0x........ is 0 bytes after a block of size 12 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + by 0x........: main (timing_safe.c:33) + +Invalid read of size 1 + at 0x........: timingsafe_bcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:40) + Address 0x........ is 0 bytes inside a block of size 12 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (timing_safe.c:38) + Block was alloc'd at + at 0x........: malloc (vg_replace_malloc.c:...) + ... + by 0x........: main (timing_safe.c:33) + +Invalid read of size 1 + at 0x........: timingsafe_memcmp (vg_replace_strmem.c:...) + by 0x........: main (timing_safe.c:41) + Address 0x........ is 0 bytes inside a block of size 12 free'd + at 0x........: free (vg_replace_malloc.c:...) + by 0x........: main (timing_safe.c:38) + Block was alloc'd at + at 0x........: malloc (vg_replace_malloc.c:...) + ... + by 0x........: main (timing_safe.c:33) + diff --git a/memcheck/tests/freebsd/timing_safe.vgtest b/memcheck/tests/freebsd/timing_safe.vgtest new file mode 100644 index 0000000000..6cbd046396 --- /dev/null +++ b/memcheck/tests/freebsd/timing_safe.vgtest @@ -0,0 +1,3 @@ +prog: timing_safe +vgopts: -q + diff --git a/memcheck/tests/freebsd/timingsafe.stderr.exp b/memcheck/tests/freebsd/timingsafe.stderr.exp deleted file mode 100644 index 5cca1f79f0..0000000000 --- a/memcheck/tests/freebsd/timingsafe.stderr.exp +++ /dev/null @@ -1,54 +0,0 @@ -Conditional jump or move depends on uninitialised value(s) - at 0x........: timingsafe_bcmp (vg_replace_strmem.c:1228) - by 0x........: main (timingsafe.c:30) - -Conditional jump or move depends on uninitialised value(s) - at 0x........: timingsafe_bcmp (vg_replace_strmem.c:0) - by 0x........: main (timingsafe.c:30) - -Conditional jump or move depends on uninitialised value(s) - at 0x........: timingsafe_memcmp (vg_replace_strmem.c:1227) - by 0x........: main (timingsafe.c:31) - -Conditional jump or move depends on uninitialised value(s) - at 0x........: timingsafe_memcmp (vg_replace_strmem.c:0) - by 0x........: main (timingsafe.c:31) - -Invalid read of size 1 - at 0x........: timingsafe_bcmp (vg_replace_strmem.c:1228) - by 0x........: main (timingsafe.c:35) - Address 0x........ is 0 bytes after a block of size 12 alloc'd - at 0x........: malloc (vg_replace_malloc.c:...) - ... - by 0x........: main (timingsafe.c:33) - -Invalid read of size 1 - at 0x........: timingsafe_memcmp (vg_replace_strmem.c:1227) - by 0x........: main (timingsafe.c:36) - Address 0x........ is 0 bytes after a block of size 12 alloc'd - at 0x........: malloc (vg_replace_malloc.c:...) - ... - by 0x........: main (timingsafe.c:33) - -Invalid read of size 1 - at 0x........: timingsafe_bcmp (vg_replace_strmem.c:1228) - by 0x........: main (timingsafe.c:40) - Address 0x........ is 0 bytes inside a block of size 12 free'd - at 0x........: free (vg_replace_malloc.c:...) - by 0x........: main (timingsafe.c:38) - Block was alloc'd at - at 0x........: malloc (vg_replace_malloc.c:...) - ... - by 0x........: main (timingsafe.c:33) - -Invalid read of size 1 - at 0x........: timingsafe_memcmp (vg_replace_strmem.c:1227) - by 0x........: main (timingsafe.c:41) - Address 0x........ is 0 bytes inside a block of size 12 free'd - at 0x........: free (vg_replace_malloc.c:...) - by 0x........: main (timingsafe.c:38) - Block was alloc'd at - at 0x........: malloc (vg_replace_malloc.c:...) - ... - by 0x........: main (timingsafe.c:33) - diff --git a/memcheck/tests/freebsd/timingsafe.vgtest b/memcheck/tests/freebsd/timingsafe.vgtest deleted file mode 100644 index 6ce16bc59b..0000000000 --- a/memcheck/tests/freebsd/timingsafe.vgtest +++ /dev/null @@ -1,3 +0,0 @@ -prog: timingsafe -vgopts: -q - diff --git a/memcheck/tests/wcsncpy.c b/memcheck/tests/wcsncpy.c new file mode 100644 index 0000000000..59bee5fe6a --- /dev/null +++ b/memcheck/tests/wcsncpy.c @@ -0,0 +1,125 @@ +/* Test strncpy functions. + Copyright (C) 1999-2023 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 + . */ + +/* This code is copied from GNU libc 2.38 string/test-strncpy.c + * Necessary bits have been copied from other headers in GNU libc. + * The code has been de-MACROed a bit and made specific for + * wcsncpy. And re-indented. */ + +#include +#include +#include +#include +#include + +# define BIG_CHAR WCHAR_MAX +# define SMALL_CHAR 1273 + +size_t page_size; +unsigned char buf1[10240]; +unsigned char buf2[10240]; + +typedef wchar_t *(*impl_t)(wchar_t *, const wchar_t *, size_t); + +static void do_one_test(impl_t impl, wchar_t *dst, const wchar_t *src, size_t len, size_t n) +{ + if (impl(dst, src, n) != dst) + { + fprintf(stderr, "Wrong result in function wscncpy %p %p", impl(dst, src, n), dst); + return; + } + + if (memcmp(dst, src, (len > n ? n : len) * sizeof(wchar_t)) != 0) + { + fprintf(stderr, "Wrong result in function wcsncpy"); + return; + } + + if (n > len) + { + size_t i; + + for (i = len; i < n; ++i) + { + if (dst[i] != '\0') + { + fprintf(stderr, "Wrong result in function wcsncpy"); + return; + } + } + } +} + +static void do_test(size_t align1, size_t align2, size_t len, size_t n, int max_char) +{ + size_t i; + wchar_t *s1, *s2; + + /* For wcsncpy: align1 and align2 here mean alignment not in bytes, + but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)). */ + align1 &= 7; + if ((align1 + len) * sizeof(wchar_t) >= page_size) + return; + + align2 &= 7; + if ((align2 + len) * sizeof(wchar_t) >= page_size) + return; + + s1 = (wchar_t *)(buf1) + align1; + s2 = (wchar_t *)(buf2) + align2; + + for (i = 0; i < len; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + for (i = len + 1; (i + align1) * sizeof(wchar_t) < page_size && i < len + 64; ++i) + s1[i] = 32 + 32 * i % (max_char - 32); + + do_one_test(wcsncpy, s2, s1, len, n); +} + +int main(void) +{ + wchar_t *bar = calloc(121, sizeof(wchar_t)); + wmemset(bar, 1, 120); + + wchar_t *foo = calloc(256, sizeof(wchar_t)); + wcsncpy(foo, bar, 255); + + page_size = sysconf (_SC_PAGE_SIZE); + + size_t i; + for (i = 1; i < 8; ++i) + { + do_test(i, i, 16, 16, SMALL_CHAR); + do_test(i, i, 16, 16, BIG_CHAR); + do_test(i, 2 * i, 16, 16, SMALL_CHAR); + do_test(2 * i, i, 16, 16, BIG_CHAR); + do_test(8 - i, 2 * i, 1 << i, 2 << i, SMALL_CHAR); + do_test(2 * i, 8 - i, 2 << i, 1 << i, SMALL_CHAR); + do_test(8 - i, 2 * i, 1 << i, 2 << i, BIG_CHAR); + do_test(2 * i, 8 - i, 2 << i, 1 << i, BIG_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test(0, 0, 4 << i, 8 << i, SMALL_CHAR); + do_test(0, 0, 16 << i, 8 << i, SMALL_CHAR); + do_test(8 - i, 2 * i, 4 << i, 8 << i, SMALL_CHAR); + do_test(8 - i, 2 * i, 16 << i, 8 << i, SMALL_CHAR); + } +} diff --git a/memcheck/tests/wcsncpy.stderr.exp b/memcheck/tests/wcsncpy.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/wcsncpy.vgtest b/memcheck/tests/wcsncpy.vgtest new file mode 100644 index 0000000000..02dbbffcf0 --- /dev/null +++ b/memcheck/tests/wcsncpy.vgtest @@ -0,0 +1,3 @@ +prereq: test -e ./wcsncpy +prog: wcsncpy +vgopts: -q diff --git a/shared/vg_replace_strmem.c b/shared/vg_replace_strmem.c index 10195b3348..8de6a0698e 100644 --- a/shared/vg_replace_strmem.c +++ b/shared/vg_replace_strmem.c @@ -105,6 +105,7 @@ 20450 WSTRNCMP 20460 MEMMEM 20470 WMEMCMP + 20480 WCSNCPY */ #if defined(VGO_solaris) @@ -2266,6 +2267,7 @@ static inline void my_exit ( int x ) WMEMCHR(VG_Z_LIBC_SONAME, wmemchr) #endif +/*---------------------- wmemcmp ----------------------*/ #define WMEMCMP(soname, fnname) \ int VG_REPLACE_FUNCTION_EZU(20470,soname,fnname) \ @@ -2280,10 +2282,52 @@ static inline void my_exit ( int x ) return 0; \ } -#if defined(VGO_linux) +#if defined(VGO_linux) || defined(VGO_freebsd) WMEMCMP(VG_Z_LIBC_SONAME, wmemcmp) #endif +/*---------------------- wcsncpy ----------------------*/ + + // This is a wchar_t equivalent to strncpy. We don't + // have wchar_t available here, but in the GNU C Library + // wchar_t is always 32 bits wide. + +#define WCSNCPY(soname, fnname) \ + Int* VG_REPLACE_FUNCTION_EZU(20480,soname,fnname) \ + ( Int* dst, const Int* src, SizeT n ); \ + Int* VG_REPLACE_FUNCTION_EZU(20480,soname,fnname) \ + ( Int* dst, const Int* src, SizeT n ) \ + { \ + const Int* src_orig = src; \ + Int* dst_orig = dst; \ + SizeT m = 0; \ + \ + while (m < n && *src) { \ + m++; \ + *dst++ = *src++; \ + } \ + \ + /* This checks for overlap after copying, unavoidable without */ \ + /* pre-counting length... should be ok */ \ + /* +4 because sizeof(wchar_t) == 4 */ \ + SizeT srclen = ((m < n) ? m+1 : n)*4; \ + RECORD_COPY(srclen); \ + if (is_overlap(dst_orig, \ + src_orig, \ + n*4, \ + srclen)) \ + RECORD_OVERLAP_ERROR("wcsncpy", dst_orig, src_orig, 0); \ + \ + while (m++ < n) { \ + *dst++ = 0; \ + } \ + \ + return dst_orig; \ + } + +#if defined(VGO_linux) || defined(VGO_freebsd) + WCSNCPY(VG_Z_LIBC_SONAME, wcsncpy) +#endif /*------------------------------------------------------------*/ /*--- Improve definedness checking of process environment ---*/