summaryrefslogtreecommitdiffstats
path: root/src/vppinfra/string.h
diff options
context:
space:
mode:
authorBenoît Ganne <bganne@cisco.com>2021-02-11 19:46:43 +0100
committerDamjan Marion <dmarion@me.com>2021-02-15 16:17:14 +0000
commit1a3e08a7197addb1c07e66c1b1da3286c9bcb140 (patch)
treefcbb03afc8aa57d3c9c63a7cdf5a27d0c24cf502 /src/vppinfra/string.h
parentce3f8249b59d3c3540cf0b87cc1c2f0d3a3a1814 (diff)
vppinfra: fix memcpy undefined behaviour
Calling mem{cpy,move} with NULL pointers results in undefined behaviour. This in turns is exploited by GCC. For example, the sequence: memcpy (dst, src, n); if (!src) return; src[0] = 0xcafe; will be optimized as memcpy (dst, src, n); src[0] = 0xcafe; IOW the test for NULL is gone. vec_*() functions sometime call memcpy with NULL pointers and 0 length, triggering this optimization. For example, the sequence: vec_append(v1, v2); len = vec_len(v2); will crash if v2 is NULL, because the test for NULL pointer in vec_len() has been optimized out. This commit fixes occurrences of such undefined behaviour, and also introduces a memcpy wrapper to catch those in debug mode. Type: fix Change-Id: I175e2dd726a883f97cf7de3b15f66d4b237ddefd Signed-off-by: Benoît Ganne <bganne@cisco.com>
Diffstat (limited to 'src/vppinfra/string.h')
-rw-r--r--src/vppinfra/string.h27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/vppinfra/string.h b/src/vppinfra/string.h
index 4f96450ce9e..fb46a0c6a0d 100644
--- a/src/vppinfra/string.h
+++ b/src/vppinfra/string.h
@@ -46,6 +46,7 @@
#include <vppinfra/clib.h> /* for CLIB_LINUX_KERNEL */
#include <vppinfra/vector.h>
+#include <vppinfra/error_bootstrap.h>
#ifdef CLIB_LINUX_KERNEL
#include <linux/string.h>
@@ -73,16 +74,30 @@ void clib_memswap (void *_a, void *_b, uword bytes);
#ifndef __COVERITY__
#if __AVX512BITALG__
#include <vppinfra/memcpy_avx512.h>
+#define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_avx512 (a, b, c)
#elif __AVX2__
#include <vppinfra/memcpy_avx2.h>
+#define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_avx2 (a, b, c)
#elif __SSSE3__
#include <vppinfra/memcpy_sse3.h>
-#else
-#define clib_memcpy_fast(a,b,c) memcpy(a,b,c)
-#endif
-#else /* __COVERITY__ */
-#define clib_memcpy_fast(a,b,c) memcpy(a,b,c)
-#endif
+#define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_sse3 (a, b, c)
+#endif /* __AVX512BITALG__ */
+#endif /* __COVERITY__ */
+
+#ifndef clib_memcpy_fast_arch
+#define clib_memcpy_fast_arch(a, b, c) memcpy (a, b, c)
+#endif /* clib_memcpy_fast_arch */
+
+static_always_inline void *
+clib_memcpy_fast (void *restrict dst, const void *restrict src, size_t n)
+{
+ ASSERT (dst && src &&
+ "memcpy(src, dst, n) with src == NULL or dst == NULL is undefined "
+ "behaviour");
+ return clib_memcpy_fast_arch (dst, src, n);
+}
+
+#undef clib_memcpy_fast_arch
/* c-11 string manipulation variants */