mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-25 10:50:08 +03:00
globals: Don't use thread-local storage on Darwin
It seems that thread-local storage destructors are run before pthread thread-specific data destructors on Darwin, defeating our scheme to use TSD to clean up TLS. Here's an example program that reports a use-after-free when compiled with `-fsanitize=address` on macOS: #include <pthread.h> typedef struct { int v; } my_struct; static _Thread_local my_struct tls; pthread_key_t key; void dtor(void *tsd) { my_struct *s = (my_struct *) tsd; /* * This will crash ASan, apparently because * TLS has already been freed. */ s->v = 1; } void *thread(void *p) { pthread_setspecific(key, &tls); return NULL; } int main(void) { pthread_key_create(&key, dtor); pthread_t handle; pthread_create(&handle, NULL, thread, NULL); pthread_join(handle, NULL); return 0; }
This commit is contained in:
parent
45470611b0
commit
bc4e82ff42
43
globals.c
43
globals.c
@ -64,13 +64,6 @@
|
||||
#define IS_MAIN_THREAD 1
|
||||
#endif
|
||||
|
||||
static int parserInitialized;
|
||||
|
||||
/*
|
||||
* Mutex to protect "ForNewThreads" variables
|
||||
*/
|
||||
static xmlMutex xmlThrDefMutex;
|
||||
|
||||
#define XML_DECLARE_MEMBER(name, type, attrs) \
|
||||
type gs_##name;
|
||||
|
||||
@ -94,9 +87,25 @@ XML_GLOBALS_TREE
|
||||
#undef XML_OP
|
||||
};
|
||||
|
||||
static int parserInitialized;
|
||||
|
||||
/*
|
||||
* Mutex to protect "ForNewThreads" variables
|
||||
*/
|
||||
static xmlMutex xmlThrDefMutex;
|
||||
|
||||
#ifdef LIBXML_THREAD_ENABLED
|
||||
|
||||
#ifdef XML_THREAD_LOCAL
|
||||
/*
|
||||
* On Darwin, thread-local storage destructors seem to be run before
|
||||
* pthread thread-specific data destructors. This causes ASan to
|
||||
* report a use-after-free.
|
||||
*/
|
||||
#if defined(XML_THREAD_LOCAL) && !defined(__APPLE__)
|
||||
#define USE_TLS
|
||||
#endif
|
||||
|
||||
#ifdef USE_TLS
|
||||
static XML_THREAD_LOCAL xmlGlobalState globalState;
|
||||
#endif
|
||||
|
||||
@ -125,7 +134,7 @@ static pthread_t mainthread;
|
||||
|
||||
#elif defined HAVE_WIN32_THREADS
|
||||
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
static DWORD globalkey = TLS_OUT_OF_INDEXES;
|
||||
#endif
|
||||
static DWORD mainthread;
|
||||
@ -564,7 +573,7 @@ void xmlInitGlobalsInternal(void) {
|
||||
pthread_key_create(&globalkey, xmlFreeGlobalState);
|
||||
mainthread = pthread_self();
|
||||
#elif defined(HAVE_WIN32_THREADS)
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
globalkey = TlsAlloc();
|
||||
#endif
|
||||
mainthread = GetCurrentThreadId();
|
||||
@ -599,7 +608,7 @@ void xmlCleanupGlobalsInternal(void) {
|
||||
#endif /* XML_PTHREAD_WEAK */
|
||||
pthread_key_delete(globalkey);
|
||||
#elif defined(HAVE_WIN32_THREADS)
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
if (globalkey != TLS_OUT_OF_INDEXES) {
|
||||
TlsFree(globalkey);
|
||||
globalkey = TLS_OUT_OF_INDEXES;
|
||||
@ -684,7 +693,7 @@ xmlFreeGlobalState(void *state)
|
||||
* so changes are dangerous.
|
||||
*/
|
||||
xmlResetError(&(gs->gs_xmlLastError));
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
free(state);
|
||||
#endif
|
||||
}
|
||||
@ -782,7 +791,7 @@ xmlInitGlobalState(xmlGlobalStatePtr gs) {
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
pthread_setspecific(globalkey, gs);
|
||||
#elif defined HAVE_WIN32_THREADS
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
TlsSetValue(globalkey, gs);
|
||||
#endif
|
||||
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
||||
@ -793,7 +802,7 @@ xmlInitGlobalState(xmlGlobalStatePtr gs) {
|
||||
gs->initialized = 1;
|
||||
}
|
||||
|
||||
#ifndef XML_THREAD_LOCAL
|
||||
#ifndef USE_TLS
|
||||
/**
|
||||
* xmlNewGlobalState:
|
||||
*
|
||||
@ -835,7 +844,7 @@ xmlGetThreadLocalStorage(int allowFailure) {
|
||||
|
||||
(void) allowFailure;
|
||||
|
||||
#ifdef XML_THREAD_LOCAL
|
||||
#ifdef USE_TLS
|
||||
gs = &globalState;
|
||||
if (gs->initialized == 0)
|
||||
xmlInitGlobalState(gs);
|
||||
@ -907,7 +916,7 @@ __xmlParserVersion(void) {
|
||||
*/
|
||||
int
|
||||
xmlCheckThreadLocalStorage(void) {
|
||||
#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_THREAD_LOCAL)
|
||||
#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
|
||||
if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
|
||||
return(-1);
|
||||
#endif
|
||||
@ -949,7 +958,7 @@ DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
|
||||
{
|
||||
switch (fdwReason) {
|
||||
case DLL_THREAD_DETACH:
|
||||
#ifdef XML_THREAD_LOCAL
|
||||
#ifdef USE_TLS
|
||||
xmlFreeGlobalState(&globalState);
|
||||
#else
|
||||
if (globalkey != TLS_OUT_OF_INDEXES) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user