From 952cd885fb6055c1e133ca53e3348d0e0b9d6cab Mon Sep 17 00:00:00 2001 From: Neil Date: Fri, 13 Dec 2019 11:29:26 +1100 Subject: Use safe mechanism to convert to function pointers. Mark noexcept where reasonable. Check that functions are available. --- src/ExternalLexer.cxx | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ExternalLexer.cxx b/src/ExternalLexer.cxx index 308846628..495b8a867 100644 --- a/src/ExternalLexer.cxx +++ b/src/ExternalLexer.cxx @@ -39,6 +39,16 @@ typedef int (EXT_LEXER_DECL *GetLexerCountFn)(); typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength); typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index); +/// Generic function to convert from a void* to a function pointer. +/// This avoids undefined and conditionally defined behaviour. +template +T FunctionPointer(void *function) noexcept { + static_assert(sizeof(T) == sizeof(function)); + T fp; + memcpy(&fp, &function, sizeof(T)); + return fp; +} + /// Sub-class of LexerModule to use an external lexer. class ExternalLexerModule : public LexerModule { protected: @@ -51,7 +61,7 @@ public: fneFactory(nullptr), name(languageName_){ languageName = name.c_str(); } - virtual void SetExternal(GetLexerFactoryFunction fFactory, int index); + void SetExternal(GetLexerFactoryFunction fFactory, int index) noexcept; }; /// LexerLibrary exists for every External Lexer DLL, contains ExternalLexerModules. @@ -71,10 +81,10 @@ public: ~LexerManager(); static LexerManager *GetInstance(); - static void DeleteInstance(); + static void DeleteInstance() noexcept; void Load(const char *path); - void Clear(); + void Clear() noexcept; private: LexerManager(); @@ -95,7 +105,7 @@ std::unique_ptr LexerManager::theInstance; // //------------------------------------------ -void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { +void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) noexcept { fneFactory = fFactory; fnFactory = fFactory(index); } @@ -111,13 +121,16 @@ LexerLibrary::LexerLibrary(const char *moduleName_) { lib.reset(DynamicLibrary::Load(moduleName_)); if (lib->IsValid()) { moduleName = moduleName_; - //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects - GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount"); + GetLexerCountFn GetLexerCount = FunctionPointer(lib->FindFunction("GetLexerCount")); if (GetLexerCount) { // Find functions in the DLL - GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName"); - GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory"); + GetLexerNameFn GetLexerName = FunctionPointer(lib->FindFunction("GetLexerName")); + GetLexerFactoryFunction fnFactory = FunctionPointer(lib->FindFunction("GetLexerFactory")); + + if (!GetLexerName || !fnFactory) { + return; + } const int nl = GetLexerCount(); @@ -158,7 +171,7 @@ LexerManager *LexerManager::GetInstance() { } /// Delete any LexerManager instance... -void LexerManager::DeleteInstance() { +void LexerManager::DeleteInstance() noexcept { theInstance.reset(); } @@ -178,7 +191,7 @@ void LexerManager::Load(const char *path) { libraries.push_back(std::make_unique(path)); } -void LexerManager::Clear() { +void LexerManager::Clear() noexcept { libraries.clear(); } -- cgit v1.2.3