From 5e13c30a04afd5f1c939f48de5991d9c288a6daa Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Tue, 7 Nov 2017 14:37:36 +0100 Subject: [PATCH] fix(general): avoid usage of void* cast in getPublic helper, very dangerous in multi inheritance case!!! --- include/linphone/utils/general.h | 58 ++++++++++++++++++++++++++------ src/db/main-db.cpp | 2 +- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/include/linphone/utils/general.h b/include/linphone/utils/general.h index cbd62d338..b03c23804 100644 --- a/include/linphone/utils/general.h +++ b/include/linphone/utils/general.h @@ -68,10 +68,10 @@ LINPHONE_BEGIN_NAMESPACE void l_assert (const char *condition, const char *file, int line); -#ifndef DEBUG - #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) -#else +#ifdef DEBUG #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : LinphonePrivate::l_assert(#CONDITION, __FILE__, __LINE__)) +#else + #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) #endif #ifndef _MSC_VER @@ -132,18 +132,54 @@ class ObjectPrivate; friend class Tester; #endif -// Generic public helper. (Neither ClonableObject.) -// `void *` is used to avoid downcasting. +namespace Private { + // See: http://en.cppreference.com/w/cpp/types/void_t + template struct MakeVoid { + typedef void type; + }; + template + using void_t = typename MakeVoid::type; + + template + struct IsMapContainerImpl : std::false_type {}; + + template + struct IsMapContainerImpl< + T, + void_t< + typename T::key_type, + typename T::mapped_type, + decltype(std::declval()[std::declval()]) + > + > : std::true_type {}; +}; + +// Check if a type is a std container like map, unordered_map... template -constexpr T *getPublicHelper (void *object, const void *) { - return static_cast(object); +struct IsMapContainer : Private::IsMapContainerImpl::type {}; + +// Generic public helper. +template< + typename R, + typename P, + typename C, + typename = typename std::enable_if::value, P>::type +> +constexpr R *getPublicHelper (P *object, const C *) { + return static_cast(object); } -template -inline T *getPublicHelper (const U *map, const ClonableObjectPrivate *context) { +// Generic public helper. Deal with shared data. +template< + typename R, + typename P, + typename C, + typename = typename std::enable_if::value, P>::type +> +inline R *getPublicHelper (const P *map, const C *context) { auto it = map->find(context); - L_ASSERT(it != map->end()); - return static_cast(it->second); + L_ASSERT(it != map->cend()); + return static_cast(it->second); } #define L_DECLARE_PUBLIC(CLASS) \ diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 8d5ca0822..989d1ce68 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -711,7 +711,7 @@ MainDb::MainDb (const shared_ptr &core) : AbstractDb(*new MainDbPrivate), "CREATE TABLE IF NOT EXISTS chat_message_content (" " id" + primaryKeyStr("BIGINT UNSIGNED") + "," - " event_id " + primaryKeyRefStr("BIGINT UNSIGNED") + "," + " event_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," " content_type_id" + primaryKeyRefStr("SMALLINT UNSIGNED") + "," " body TEXT NOT NULL,"