Merge branch 'lsan-dynamic-loading' into 'main'

glib-private: Check for LSAN support at runtime when controlling it

See merge request GNOME/glib!3672
This commit is contained in:
Philip Withnall 2023-10-29 20:40:11 +00:00
commit 6d45bdb1bf
2 changed files with 56 additions and 6 deletions

View File

@ -37,14 +37,51 @@
/*
* %_GLIB_ADDRESS_SANITIZER:
*
* Private macro defined if the AddressSanitizer is in use.
* Private macro defined if the AddressSanitizer is in use by GLib itself.
*/
#define _GLIB_ADDRESS_SANITIZER
#include <sanitizer/lsan_interface.h>
/* If GLib itself is not compiled with ASAN sanitizer we may still want to
* control it in case it's linked by the loading application, so we need to
* do this check dynamically.
* However MinGW doesn't support weak attribute properly (even if it advertises
* it), so we ignore it in such case since it's not convenient to go through
* dlsym().
* Under MSVC we could use alternatename, but it doesn't seem to be as reliable
* as we'd like: https://stackoverflow.com/a/11529277/210151 and
* https://devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024
*/
#elif defined (G_OS_UNIX) && g_macro__has_attribute (weak)
#define HAS_DYNAMIC_ASAN_LOADING
void __lsan_enable (void) __attribute__ ((weak));
void __lsan_disable (void) __attribute__ ((weak));
void __lsan_ignore_object (const void *p) __attribute__ ((weak));
#endif
/*
* g_leak_sanitizer_is_supported:
*
* Checks at runtime if LeakSanitizer is currently supported by the running
* binary. This may imply that GLib itself is not compiled with sanitizer
* but that the loading program is.
*/
static inline gboolean
g_leak_sanitizer_is_supported (void)
{
#if defined (_GLIB_ADDRESS_SANITIZER)
return TRUE;
#elif defined (HAS_DYNAMIC_ASAN_LOADING)
return __lsan_enable != NULL && __lsan_ignore_object != NULL;
#else
return FALSE;
#endif
}
/*
* g_ignore_leak:
* @p: any pointer
@ -57,9 +94,12 @@
static inline void
g_ignore_leak (gconstpointer p)
{
#ifdef _GLIB_ADDRESS_SANITIZER
#if defined (_GLIB_ADDRESS_SANITIZER)
if (p != NULL)
__lsan_ignore_object (p);
#elif defined (HAS_DYNAMIC_ASAN_LOADING)
if (p != NULL && __lsan_ignore_object != NULL)
__lsan_ignore_object (p);
#endif
}
@ -73,9 +113,11 @@ g_ignore_leak (gconstpointer p)
static inline void
g_ignore_strv_leak (GStrv strv)
{
#ifdef _GLIB_ADDRESS_SANITIZER
gchar **item;
if (!g_leak_sanitizer_is_supported ())
return;
if (strv)
{
g_ignore_leak (strv);
@ -83,7 +125,6 @@ g_ignore_strv_leak (GStrv strv)
for (item = strv; *item != NULL; item++)
g_ignore_leak (*item);
}
#endif
}
/*
@ -98,8 +139,11 @@ g_ignore_strv_leak (GStrv strv)
static inline void
g_begin_ignore_leaks (void)
{
#ifdef _GLIB_ADDRESS_SANITIZER
#if defined (_GLIB_ADDRESS_SANITIZER)
__lsan_disable ();
#elif defined (HAS_DYNAMIC_ASAN_LOADING)
if (__lsan_disable != NULL)
__lsan_disable ();
#endif
}
@ -112,11 +156,16 @@ g_begin_ignore_leaks (void)
static inline void
g_end_ignore_leaks (void)
{
#ifdef _GLIB_ADDRESS_SANITIZER
#if defined (_GLIB_ADDRESS_SANITIZER)
__lsan_enable ();
#elif defined (HAS_DYNAMIC_ASAN_LOADING)
if (__lsan_enable != NULL)
__lsan_enable ();
#endif
}
#undef HAS_DYNAMIC_ASAN_LOADING
GMainContext * g_get_worker_context (void);
gboolean g_check_setuid (void);
GMainContext * g_main_context_new_with_next_id (guint next_id);

View File

@ -185,6 +185,7 @@
#define g_macro__has_attribute___pure__ G_GNUC_CHECK_VERSION (2, 96)
#define g_macro__has_attribute___sentinel__ G_GNUC_CHECK_VERSION (4, 0)
#define g_macro__has_attribute___unused__ G_GNUC_CHECK_VERSION (2, 4)
#define g_macro__has_attribute___weak__ G_GNUC_CHECK_VERSION (2, 8)
#define g_macro__has_attribute_cleanup G_GNUC_CHECK_VERSION (3, 3)
#define g_macro__has_attribute_fallthrough G_GNUC_CHECK_VERSION (6, 0)
#define g_macro__has_attribute_may_alias G_GNUC_CHECK_VERSION (3, 3)