Skip to content

Commit 018fc85

Browse files
iluuu1994ju1ius
authored andcommitted
Disable LSan tls
LSan crashes a lot recently, and it seems to be caused by tls. Since we're not actually making use of C11s _Thread_local we can set the use_tls=0 option. This causes a false positive in dlopen() that apprently uses thread locals. We suppress this with __lsan_disable()/__lsan_enable(). Co-authored-by: ju1ius <[email protected]>
1 parent 1bdaf6c commit 018fc85

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

Zend/zend_portability.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,47 @@
159159
# define PHP_RTLD_MODE RTLD_LAZY
160160
# endif
161161

162+
# ifdef __SANITIZE_ADDRESS__
163+
# include "sanitizer/lsan_interface.h"
164+
# endif
165+
166+
/* dl uses a thread local variable internally. Due to LSan crashing we're setting use_tls=0, which
167+
* will report a leak inside dlopen() that we need to suppress. */
168+
static inline void *zend_dlopen(const char *file, int mode)
169+
{
170+
# ifdef __SANITIZE_ADDRESS__
171+
__lsan_disable();
172+
# endif
173+
void *ptr = dlopen(file, mode);
174+
# ifdef __SANITIZE_ADDRESS__
175+
__lsan_enable();
176+
# endif
177+
return ptr;
178+
}
162179
# if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
163-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
180+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
164181
# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
165-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
182+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
166183
# else
167-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
184+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
168185
# endif
186+
187+
static inline void *zend_dlsym(void *__restrict handle, const char *__restrict name)
188+
{
189+
# ifdef __SANITIZE_ADDRESS__
190+
__lsan_disable();
191+
# endif
192+
void *ptr = dlsym(handle, name);
193+
# ifdef __SANITIZE_ADDRESS__
194+
__lsan_enable();
195+
# endif
196+
return ptr;
197+
}
169198
# define DL_UNLOAD dlclose
170199
# if defined(DLSYM_NEEDS_UNDERSCORE)
171-
# define DL_FETCH_SYMBOL(h,s) dlsym((h), "_" s)
200+
# define DL_FETCH_SYMBOL(h,s) zend_dlsym((h), "_" s)
172201
# else
173-
# define DL_FETCH_SYMBOL dlsym
202+
# define DL_FETCH_SYMBOL zend_dlsym
174203
# endif
175204
# define DL_ERROR dlerror
176205
# define DL_HANDLE void *

ext/readline/readline_cli.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ this extension sharedto offer compatibility.
754754
do { \
755755
(cb) = NULL; \
756756
cli_shell_callbacks_t *(*get_callbacks)(void); \
757-
get_callbacks = dlsym(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
757+
get_callbacks = DL_FETCH_SYMBOL(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
758758
if (get_callbacks) { \
759759
(cb) = get_callbacks(); \
760760
} \

run-tests.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ function main(): void
586586
$lsanSuppressions = __DIR__ . '/.github/lsan-suppressions.txt';
587587
if (file_exists($lsanSuppressions)) {
588588
$environment['LSAN_OPTIONS'] = 'suppressions=' . $lsanSuppressions
589-
. ':print_suppressions=0';
589+
. ':print_suppressions=0:use_tls=0:fast_unwind_on_malloc=false';
590590
}
591591
break;
592592
case '--repeat':

0 commit comments

Comments
 (0)