]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 475652 - Missing suppression for __wcsncpy_avx2 (strncpy-avx2.S:308)?
authorPaul Floyd <pjfloyd@wanadoo.fr>
Mon, 16 Oct 2023 21:14:39 +0000 (23:14 +0200)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Mon, 16 Oct 2023 21:14:39 +0000 (23:14 +0200)
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.

14 files changed:
.gitignore
NEWS
configure.ac
memcheck/tests/Makefile.am
memcheck/tests/freebsd/Makefile.am
memcheck/tests/freebsd/timing_safe.c [moved from memcheck/tests/freebsd/timingsafe.c with 100% similarity]
memcheck/tests/freebsd/timing_safe.stderr.exp [new file with mode: 0644]
memcheck/tests/freebsd/timing_safe.vgtest [new file with mode: 0644]
memcheck/tests/freebsd/timingsafe.stderr.exp [deleted file]
memcheck/tests/freebsd/timingsafe.vgtest [deleted file]
memcheck/tests/wcsncpy.c [new file with mode: 0644]
memcheck/tests/wcsncpy.stderr.exp [new file with mode: 0644]
memcheck/tests/wcsncpy.vgtest [new file with mode: 0644]
shared/vg_replace_strmem.c

index 68f3a837627e0add0353d60c7697fee0ca2b78bc..e017762144ad00f0b0ac5b954ce286c6587c0f1f 100644 (file)
 /memcheck/tests/wcs
 /memcheck/tests/weirdioctl
 /memcheck/tests/with space
+/memcheck/tests/wcsncpy
 /memcheck/tests/wmemcmp
 /memcheck/tests/wrap1
 /memcheck/tests/wrap2
 /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 b2a385d8df983cc081cb25cda89dbc25682e5c77..cd73fa47d10e3d71b5ef07fd9e8631e02919a2cf 100644 (file)
--- 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
 
index 357e6588fd116e3f8c8e29c09d5f3075f5c27630..a35b9aa301e01ea1eae657da017cd15090ef3301 100755 (executable)
@@ -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 \
index 12d959566881b3ddf90dd782f2f6503bff9e5711..87ae8d94e6554d7636b52e2c2d179019364ddbd2 100644 (file)
@@ -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)
 
index 23298e9ecdccc896d463263d87e567a0e1108c49..0e45aeab61b6c99bfa33f52fc1af4dd4739b5f83 100644 (file)
@@ -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/timing_safe.stderr.exp b/memcheck/tests/freebsd/timing_safe.stderr.exp
new file mode 100644 (file)
index 0000000..f1aa70e
--- /dev/null
@@ -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 (file)
index 0000000..6cbd046
--- /dev/null
@@ -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 (file)
index 5cca1f7..0000000
+++ /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 (file)
index 6ce16bc..0000000
+++ /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 (file)
index 0000000..59bee5f
--- /dev/null
@@ -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
+   <https://www.gnu.org/licenses/>.  */
+
+/* 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <unistd.h>
+
+# 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 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/wcsncpy.vgtest b/memcheck/tests/wcsncpy.vgtest
new file mode 100644 (file)
index 0000000..02dbbff
--- /dev/null
@@ -0,0 +1,3 @@
+prereq: test -e ./wcsncpy
+prog: wcsncpy
+vgopts: -q
index 10195b3348533a588f44b62cb151f066e0be3fa0..8de6a0698eb3da6e98e2733a2ad42b6287ac9a28 100644 (file)
    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  ---*/