Skip to content

Commit 1c75ea8

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 <jules.bernable@gmail.com>
1 parent d861e01 commit 1c75ea8

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
@@ -162,18 +162,47 @@
162162
# define PHP_RTLD_MODE RTLD_LAZY
163163
# endif
164164

165+
# ifdef __SANITIZE_ADDRESS__
166+
# include "sanitizer/lsan_interface.h"
167+
# endif
168+
169+
/* dl uses a thread local variable internally. Due to LSan crashing we're setting use_tls=0, which
170+
* will report a leak inside dlopen() that we need to suppress. */
171+
static inline void *zend_dlopen(const char *file, int mode)
172+
{
173+
# ifdef __SANITIZE_ADDRESS__
174+
__lsan_disable();
175+
# endif
176+
void *ptr = dlopen(file, mode);
177+
# ifdef __SANITIZE_ADDRESS__
178+
__lsan_enable();
179+
# endif
180+
return ptr;
181+
}
165182
# if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
166-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
183+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
167184
# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
168-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
185+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
169186
# else
170-
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
187+
# define DL_LOAD(libname) zend_dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
171188
# endif
189+
190+
static inline void *zend_dlsym(void *__restrict handle, const char *__restrict name)
191+
{
192+
# ifdef __SANITIZE_ADDRESS__
193+
__lsan_disable();
194+
# endif
195+
void *ptr = dlsym(handle, name);
196+
# ifdef __SANITIZE_ADDRESS__
197+
__lsan_enable();
198+
# endif
199+
return ptr;
200+
}
172201
# define DL_UNLOAD dlclose
173202
# if defined(DLSYM_NEEDS_UNDERSCORE)
174-
# define DL_FETCH_SYMBOL(h,s) dlsym((h), "_" s)
203+
# define DL_FETCH_SYMBOL(h,s) zend_dlsym((h), "_" s)
175204
# else
176-
# define DL_FETCH_SYMBOL dlsym
205+
# define DL_FETCH_SYMBOL zend_dlsym
177206
# endif
178207
# define DL_ERROR dlerror
179208
# 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)