diff options
author | Benoît Ganne <bganne@cisco.com> | 2021-02-11 19:46:43 +0100 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2021-02-15 16:17:14 +0000 |
commit | 1a3e08a7197addb1c07e66c1b1da3286c9bcb140 (patch) | |
tree | fcbb03afc8aa57d3c9c63a7cdf5a27d0c24cf502 /src/vppinfra/string.h | |
parent | ce3f8249b59d3c3540cf0b87cc1c2f0d3a3a1814 (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.h | 27 |
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 */ |