Skip to content

Commit 97fdedb

Browse files
committed
fix more reinterpret_cast edge cases
fix wglGetProcAddress can sentinel value edge case
1 parent fedf650 commit 97fdedb

3 files changed

Lines changed: 73 additions & 14 deletions

File tree

src/libprojectM/Renderer/PlatformGLContextCheck.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ enum : std::uint16_t
2323
PM_GL_CONTEXT_PROFILE_MASK = 0x9126
2424
};
2525

26-
enum : std::uint8_t
26+
enum : std::uint32_t
2727
{
28-
PM_GL_CONTEXT_CORE_PROFILE_BIT = 0x00000001,
29-
PM_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT = 0x00000002
28+
PM_GL_CONTEXT_CORE_PROFILE_BIT = 0x00000001u,
29+
PM_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT = 0x00000002u
3030
};
3131

32-
enum : std::uint8_t
32+
enum : std::uint32_t
3333
{
34-
PM_GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = 0x00000001,
35-
PM_GL_CONTEXT_FLAG_DEBUG_BIT = 0x00000002,
36-
PM_GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT = 0x00000004
34+
PM_GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = 0x00000001u,
35+
PM_GL_CONTEXT_FLAG_DEBUG_BIT = 0x00000002u,
36+
PM_GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT = 0x00000004u
3737
};
3838

3939
auto SafeStr(const unsigned char* str) -> const char*

src/libprojectM/Renderer/PlatformGLResolver.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ void GLResolver::ResolveProviderFunctions()
313313
}
314314
if (sym != nullptr)
315315
{
316-
m_eglGetProcAddress = reinterpret_cast<EglGetProcAddressFn>(sym);
316+
m_eglGetProcAddress = SymbolToFunction<EglGetProcAddressFn>(sym);
317317
}
318318
}
319319

@@ -328,7 +328,7 @@ void GLResolver::ResolveProviderFunctions()
328328
}
329329
if (sym != nullptr)
330330
{
331-
m_wglGetProcAddress = reinterpret_cast<WglGetProcAddressFn>(sym);
331+
m_wglGetProcAddress = SymbolToFunction<WglGetProcAddressFn>(sym);
332332
}
333333
}
334334
#else
@@ -353,7 +353,7 @@ void GLResolver::ResolveProviderFunctions()
353353
}
354354
if (sym != nullptr)
355355
{
356-
m_glxGetProcAddress = reinterpret_cast<GlxGetProcAddressFn>(sym);
356+
m_glxGetProcAddress = SymbolToFunction<GlxGetProcAddressFn>(sym);
357357
}
358358
}
359359
#endif
@@ -437,7 +437,7 @@ namespace {
437437
*/
438438
auto gladBridgeResolverThunk(const char* name) -> GLADapiproc
439439
{
440-
return reinterpret_cast<GLADapiproc>(GLResolver::GladResolverThunk(name));
440+
return SymbolToFunction<GLADapiproc>(GLResolver::GladResolverThunk(name));
441441
}
442442

443443
} // namespace
@@ -509,7 +509,7 @@ auto GLResolver::ResolveUnlocked(const char* name,
509509
EglProc proc = eglGetProcAddressFn(name);
510510
if (proc != nullptr)
511511
{
512-
return reinterpret_cast<void*>(proc);
512+
return FunctionToSymbol(proc);
513513
}
514514
}
515515

@@ -519,7 +519,7 @@ auto GLResolver::ResolveUnlocked(const char* name,
519519
auto proc = glxGetProcAddressFn(reinterpret_cast<const unsigned char*>(name));
520520
if (proc != nullptr)
521521
{
522-
return reinterpret_cast<void*>(proc);
522+
return FunctionToSymbol(proc);
523523
}
524524
}
525525
#else
@@ -528,7 +528,13 @@ auto GLResolver::ResolveUnlocked(const char* name,
528528
PROC proc = wglGetProcAddressFn(name);
529529
if (proc != nullptr)
530530
{
531-
return reinterpret_cast<void*>(proc);
531+
// wglGetProcAddress can return special sentinel values (1,2,3,-1) for core symbols.
532+
// Treat those as invalid and allow fallback to GetProcAddress/dlsym paths.
533+
const std::uintptr_t raw = FunctionToInteger(proc);
534+
if (raw != 1u && raw != 2u && raw != 3u && raw != static_cast<std::uintptr_t>(~0u))
535+
{
536+
return FunctionToSymbol(proc);
537+
}
532538
}
533539
}
534540
#endif

src/libprojectM/Renderer/PlatformLoader.hpp

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

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

@@ -363,6 +364,58 @@ auto SymbolToFunction(void* symbol) -> Fn
363364
return func;
364365
}
365366

367+
/**
368+
* @brief Converts a function pointer into a symbol pointer representation without UB.
369+
*
370+
* The inverse of SymbolToFunction(). This is used at API boundaries where legacy
371+
* interfaces represent procedure addresses as void*.
372+
*
373+
* @tparam Fn Function pointer type.
374+
* @param func Function pointer.
375+
* @return Symbol pointer as void* or nullptr if not representable.
376+
*/
377+
template <typename Fn>
378+
auto FunctionToSymbol(Fn func) -> void*
379+
{
380+
if (func == nullptr)
381+
{
382+
return nullptr;
383+
}
384+
385+
if (sizeof(Fn) != sizeof(void*))
386+
{
387+
return nullptr;
388+
}
389+
390+
void* symbol = nullptr;
391+
std::memcpy(&symbol, &func, sizeof(void*));
392+
return symbol;
393+
}
394+
395+
/**
396+
* @brief Converts a function pointer into an integer representation (best-effort).
397+
*
398+
* Useful for validating platform-specific sentinel values (e.g. Windows WGL).
399+
* Returns 0 if the conversion is not representable.
400+
*/
401+
template <typename Fn>
402+
auto FunctionToInteger(Fn func) -> std::uintptr_t
403+
{
404+
if (func == nullptr)
405+
{
406+
return 0;
407+
}
408+
409+
if (sizeof(Fn) != sizeof(void*))
410+
{
411+
return 0;
412+
}
413+
414+
std::uintptr_t value = 0;
415+
std::memcpy(&value, &func, sizeof(std::uintptr_t));
416+
return value;
417+
}
418+
366419
inline auto IsCurrentEgl(const DynamicLibrary& eglLib) -> bool
367420
{
368421
if (!eglLib.IsOpen())

0 commit comments

Comments
 (0)