Skip to content

Commit fedf650

Browse files
committed
avoid reinterpret_cast
1 parent b68012d commit fedf650

1 file changed

Lines changed: 41 additions & 4 deletions

File tree

src/libprojectM/Renderer/PlatformLoader.hpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <cstddef>
4+
#include <cstring>
45
#include <string>
56

67
#ifndef __EMSCRIPTEN__
@@ -330,6 +331,38 @@ auto IsCurrentWgl() -> bool;
330331

331332
// ---------------- Inline implementations -----------------------------------
332333

334+
/**
335+
* @brief Converts a symbol pointer (void*) into a function pointer type without UB.
336+
*
337+
* dlsym/GetProcAddress return data pointers (void* / FARPROC). Converting those to function
338+
* pointers via reinterpret_cast is technically undefined behavior in C++.
339+
*
340+
* This helper uses memcpy to transfer the representation into a function pointer type.
341+
* If the platform uses different sizes for data pointers and function pointers, the
342+
* conversion fails and returns nullptr.
343+
*
344+
* @tparam Fn Function pointer type.
345+
* @param symbol Symbol pointer as void*.
346+
* @return Function pointer or nullptr.
347+
*/
348+
template <typename Fn>
349+
auto SymbolToFunction(void* symbol) -> Fn
350+
{
351+
if (symbol == nullptr)
352+
{
353+
return nullptr;
354+
}
355+
356+
if (sizeof(Fn) != sizeof(void*))
357+
{
358+
return nullptr;
359+
}
360+
361+
Fn func = nullptr;
362+
std::memcpy(&func, &symbol, sizeof(Fn));
363+
return func;
364+
}
365+
333366
inline auto IsCurrentEgl(const DynamicLibrary& eglLib) -> bool
334367
{
335368
if (!eglLib.IsOpen())
@@ -338,7 +371,8 @@ inline auto IsCurrentEgl(const DynamicLibrary& eglLib) -> bool
338371
}
339372

340373
using EglGetCurrentContext = void* (*)();
341-
auto func = reinterpret_cast<EglGetCurrentContext>(eglLib.GetSymbol("eglGetCurrentContext"));
374+
void* sym = eglLib.GetSymbol("eglGetCurrentContext");
375+
auto func = SymbolToFunction<EglGetCurrentContext>(sym);
342376
return func != nullptr && func() != nullptr;
343377
}
344378

@@ -352,10 +386,12 @@ inline auto IsCurrentGlx(const DynamicLibrary& glLib) -> bool
352386

353387
using GlxGetCurrentContext = void* (*)();
354388

355-
auto func = reinterpret_cast<GlxGetCurrentContext>(glLib.GetSymbol("glXGetCurrentContextARB"));
389+
void* sym = glLib.GetSymbol("glXGetCurrentContextARB");
390+
auto func = SymbolToFunction<GlxGetCurrentContext>(sym);
356391
if (func == nullptr)
357392
{
358-
func = reinterpret_cast<GlxGetCurrentContext>(glLib.GetSymbol("glXGetCurrentContext"));
393+
sym = glLib.GetSymbol("glXGetCurrentContext");
394+
func = SymbolToFunction<GlxGetCurrentContext>(sym);
359395
}
360396

361397
return func != nullptr && func() != nullptr;
@@ -371,7 +407,8 @@ inline auto IsCurrentWgl() -> bool
371407
}
372408

373409
using WglGetCurrentContext = void* (WINAPI*)(void);
374-
auto func = reinterpret_cast<WglGetCurrentContext>(::GetProcAddress(glModule, "wglGetCurrentContext"));
410+
void* sym = reinterpret_cast<void*>(::GetProcAddress(glModule, "wglGetCurrentContext"));
411+
auto func = SymbolToFunction<WglGetCurrentContext>(sym);
375412
return func != nullptr && func() != nullptr;
376413
}
377414

0 commit comments

Comments
 (0)