From a8e336c2b57ff1e38f2a511aab8c2c6060c1796d Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Wed, 8 Sep 2021 18:00:42 -0400 Subject: [PATCH] common: prevent using memset on non-POD types MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit While converting some code to use C++ constructs, it can be easy to forget to change some spot that uses memset to initialize or move the object. Add a templated deleted declaration to prevent using memset on types that aren't POD. For example, if I make lttng_ust_event non-POD, in src/bin/lttng-sessiond/trace-ust.h, I get this error: CXX save.lo /home/simark/src/lttng-tools/src/bin/lttng-sessiond/save.cpp: In function ‘int save_agent_events(config_writer*, agent*)’: /home/simark/src/lttng-tools/src/bin/lttng-sessiond/save.cpp:1246:23: error: use of deleted function ‘void* memset(T*, int, size_t) [with T = ltt_ust_event; = void; size_t = long unsigned int]’ 1246 | memset(&fake_event, 0, sizeof(fake_event)); | ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from /home/simark/src/lttng-tools/src/common/defaults.h:14, from /home/simark/src/lttng-tools/src/bin/lttng-sessiond/save.cpp:15: /home/simark/src/lttng-tools/src/common/macros.h:128:7: note: declared here 128 | void *memset(T *s, int c, size_t n) = delete; | ^~~~~~ Note: I tried applying this to memcpy as well, but Clang gave me some troubles with its -Waddress-of-packed-member diagnostic, so I gave up. Change-Id: Id55735db15901c6fc5d58e9b6b6b689733302398 Signed-off-by: Simon Marchi Signed-off-by: Jérémie Galarneau --- src/common/macros.hpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/common/macros.hpp b/src/common/macros.hpp index 49f163b42..b734652ee 100644 --- a/src/common/macros.hpp +++ b/src/common/macros.hpp @@ -136,14 +136,45 @@ T *malloc(size_t size) */ template -struct is_pod_or_void +struct can_free { - static constexpr bool value = std::is_pod::value || std::is_void::value; + static constexpr bool value = std::is_trivially_destructible::value || std::is_void::value; }; -template::value>::type> +template::value>::type> void free(T *p) = delete; +template +struct can_memset +{ + static constexpr bool value = std::is_pod::value || std::is_void::value; +}; + +template ::value>::type> +void *memset(T *s, int c, size_t n) = delete; + +template +struct can_memcpy +{ + static constexpr bool value = std::is_trivially_copyable::value; +}; + +template ::value>::type, + typename = typename std::enable_if::value>::type> +void *memcpy(T *d, const U *s, size_t n) = delete; + +template +struct can_memmove +{ + static constexpr bool value = std::is_trivially_copyable::value; +}; + +template ::value>::type, + typename = typename std::enable_if::value>::type> +void *memmove(T *d, const U *s, size_t n) = delete; + #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0]))) #endif -- 2.34.1