Skip to content

Fix lsan test suite #15099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
#endif

#if SANITIZER_EMSCRIPTEN
#define __ATTRP_C11_THREAD ((void*)(uptr)-1)
extern "C" {
int emscripten_builtin_pthread_create(void *thread, void *attr,
void *(*callback)(void *), void *arg);
Expand Down Expand Up @@ -452,7 +453,7 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr,
ENSURE_LSAN_INITED;
EnsureMainThreadIDIsCorrect();
__sanitizer_pthread_attr_t myattr;
if (!attr) {
if (!attr || attr == __ATTRP_C11_THREAD) {
pthread_attr_init(&myattr);
attr = &myattr;
}
Expand Down
2 changes: 2 additions & 0 deletions tests/core/test_dynamic_cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ struct Derived : Support {};
int main() {
Support* p = new Derived;
dynamic_cast<Derived*>(p)->f();
delete p;
return 0;
}
58 changes: 41 additions & 17 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ def can_do_standalone(self):
not self.get_setting('MINIMAL_RUNTIME') and \
not self.get_setting('SAFE_HEAP') and \
not self.get_setting('MEMORY64') and \
'-fsanitize=address' not in self.emcc_args
'-fsanitize=address' not in self.emcc_args and \
'-fsanitize=leak' not in self.emcc_args


def also_with_wasmfs(func):
Expand Down Expand Up @@ -660,6 +661,7 @@ def test_align64(self):
''')

@no_asan('asan errors on corner cases we check')
@no_lsan('lsan errors on corner cases we check')
def test_aligned_alloc(self):
self.do_runf(test_file('test_aligned_alloc.c'), '',
emcc_args=['-Wno-non-power-of-two-alignment'])
Expand Down Expand Up @@ -873,6 +875,7 @@ def test_stack_placement(self):
self.do_core_test('test_stack_placement.c')

@no_asan('asan does not support main modules')
@no_lsan('asan does not support main modules')
@no_wasm2js('MAIN_MODULE support')
def test_stack_placement_pic(self):
self.set_setting('TOTAL_STACK', 1024)
Expand Down Expand Up @@ -1282,7 +1285,8 @@ def test_exceptions_allowed(self):
# empty list acts the same as fully disabled
self.assertEqual(empty_size, disabled_size)
# big change when we disable exception catching of the function
self.assertGreater(size - empty_size, 0.01 * size)
if '-fsanitize=leak' not in self.emcc_args:
self.assertGreater(size - empty_size, 0.01 * size)
# full disable can remove a little bit more
self.assertLess(disabled_size, fake_size)

Expand Down Expand Up @@ -1567,6 +1571,7 @@ def test_segfault(self):

struct Classey {
virtual void doIt() = 0;
virtual ~Classey() = default;
};

struct D1 : Classey {
Expand All @@ -1581,11 +1586,11 @@ def test_segfault(self):
return 0;
});

int main(int argc, char **argv)
{
int main(int argc, char **argv) {
Classey *p = argc == 100 ? new D1() : (Classey*)%s;

p->doIt();
delete p;

return 0;
}
Expand Down Expand Up @@ -1767,16 +1772,17 @@ def test_set_align(self):

self.do_core_test('test_set_align.c')

@no_asan('EXPORT_ALL is not compatible with Asan')
def test_emscripten_api(self):
self.set_setting('EXPORTED_FUNCTIONS', ['_main', '_save_me_aimee'])
self.do_core_test('test_emscripten_api.cpp')

# test EXPORT_ALL
self.set_setting('EXPORTED_FUNCTIONS', [])
self.set_setting('EXPORT_ALL')
self.set_setting('LINKABLE')
self.do_core_test('test_emscripten_api.cpp')
# Sanitizers are not compatible with LINKABLE (dynamic linking.
if not is_sanitizing(self.emcc_args):
# test EXPORT_ALL
self.set_setting('EXPORTED_FUNCTIONS', [])
self.set_setting('EXPORT_ALL')
self.set_setting('LINKABLE')
self.do_core_test('test_emscripten_api.cpp')

def test_emscripten_run_script_string_int(self):
src = r'''
Expand Down Expand Up @@ -1921,7 +1927,6 @@ def test_em_asm_2(self):
# Tests various different ways to invoke the MAIN_THREAD_EM_ASM(), MAIN_THREAD_EM_ASM_INT() and MAIN_THREAD_EM_ASM_DOUBLE() macros.
# This test is identical to test_em_asm_2, just search-replaces EM_ASM to MAIN_THREAD_EM_ASM on the test file. That way if new
# test cases are added to test_em_asm_2.cpp for EM_ASM, they will also get tested in MAIN_THREAD_EM_ASM form.
@no_asan('Cannot use ASan: test depends exactly on heap size')
def test_main_thread_em_asm(self):
src = read_file(test_file('core/test_em_asm_2.cpp'))
create_file('src.cpp', src.replace('EM_ASM', 'MAIN_THREAD_EM_ASM'))
Expand Down Expand Up @@ -1972,10 +1977,8 @@ def test_em_asm_direct(self):
'linked_c': (['-s', 'MAIN_MODULE'], True),
})
def test_em_js(self, args, force_c):
if 'MAIN_MODULE' in args and not self.is_wasm():
self.skipTest('main module support for non-wasm')
if '-fsanitize=address' in self.emcc_args:
self.skipTest('no dynamic library support in asan yet')
if 'MAIN_MODULE' in args:
self.check_dylink()
self.emcc_args += args + ['-s', 'EXPORTED_FUNCTIONS=_main,_malloc']

self.do_core_test('test_em_js.cpp', force_c=force_c)
Expand Down Expand Up @@ -2108,6 +2111,7 @@ def test_memorygrowth_3_force_fail_reallocBuffer(self):
'grow': (['-sALLOW_MEMORY_GROWTH', '-sMAXIMUM_MEMORY=18MB'],)
})
@no_asan('requires more memory when growing')
@no_lsan('requires more memory when growing')
@no_memory64('does not fail under wasm64')
def test_aborting_new(self, args):
# test that C++ new properly errors if we fail to malloc when growth is
Expand All @@ -2117,6 +2121,7 @@ def test_aborting_new(self, args):

@no_wasm2js('no WebAssembly.Memory()')
@no_asan('ASan alters the memory size')
@no_lsan('LSan alters the memory size')
def test_module_wasm_memory(self):
self.emcc_args += ['--pre-js', test_file('core/test_module_wasm_memory.js')]
self.set_setting('IMPORTED_MEMORY')
Expand Down Expand Up @@ -2402,6 +2407,7 @@ def test_atexit(self):
self.set_setting('EXIT_RUNTIME')
self.do_core_test('test_atexit.c')

@no_lsan('https://github.com/emscripten-core/emscripten/issues/15988')
def test_atexit_threads_stub(self):
# also tests thread exit (__cxa_thread_atexit)
self.set_setting('EXIT_RUNTIME')
Expand Down Expand Up @@ -5288,6 +5294,7 @@ def test_utf8_invalid(self):
def test_minimal_runtime_utf8_invalid(self):
self.set_setting('EXPORTED_RUNTIME_METHODS', ['UTF8ToString', 'stringToUTF8'])
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
for decoder_mode in [False, True]:
self.set_setting('TEXTDECODER', decoder_mode)
print(str(decoder_mode))
Expand Down Expand Up @@ -5845,6 +5852,7 @@ def test_whets(self):
# node is slower, and fail on 64-bit
@require_v8
@no_asan('depends on the specifics of memory size, which for asan we are forced to increase')
@no_lsan('depends on the specifics of memory size, which for lsan we are forced to increase')
def test_dlmalloc_inline(self):
# needed with typed arrays
self.set_setting('INITIAL_MEMORY', '128mb')
Expand All @@ -5856,6 +5864,7 @@ def test_dlmalloc_inline(self):
# node is slower, and fail on 64-bit
@require_v8
@no_asan('depends on the specifics of memory size, which for asan we are forced to increase')
@no_lsan('depends on the specifics of memory size, which for lsan we are forced to increase')
def test_dlmalloc(self):
# needed with typed arrays
self.set_setting('INITIAL_MEMORY', '128mb')
Expand Down Expand Up @@ -5887,11 +5896,13 @@ def test_dlmalloc(self):

# Tests that a large allocation should gracefully fail
@no_asan('the memory size limit here is too small for asan')
@no_lsan('the memory size limit here is too small for lsan')
def test_dlmalloc_large(self):
self.emcc_args += ['-s', 'ABORTING_MALLOC=0', '-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'MAXIMUM_MEMORY=128MB']
self.do_runf(test_file('dlmalloc_test_large.c'), '0 0 0 1')

@no_asan('asan also changes malloc, and that ends up linking in new twice')
@no_lsan('lsan also changes malloc, and that ends up linking in new twice')
def test_dlmalloc_partial(self):
# present part of the symbols of dlmalloc, not all
src = read_file(test_file('new.cpp')).replace('{{{ NEW }}}', 'new int').replace('{{{ DELETE }}}', 'delete') + '''
Expand All @@ -5905,6 +5916,7 @@ def test_dlmalloc_partial(self):
self.do_run(src, 'new 4!\n*1,0*')

@no_asan('asan also changes malloc, and that ends up linking in new twice')
@no_lsan('lsan also changes malloc, and that ends up linking in new twice')
def test_dlmalloc_partial_2(self):
if 'SAFE_HEAP' in str(self.emcc_args):
self.skipTest('we do unsafe stuff here')
Expand Down Expand Up @@ -6397,7 +6409,7 @@ def do_test():
self.set_setting('ALLOW_MEMORY_GROWTH', 0)
do_test()

if '-fsanitize=address' in self.emcc_args:
if is_sanitizing(self.emcc_args):
# In ASan mode we need a large initial memory (or else wasm-ld fails).
# The OpenJPEG CMake will build several executables (which we need parts
# of in our testing, see above), so we must enable the flag for them all.
Expand Down Expand Up @@ -7715,6 +7727,7 @@ def test_asyncify_during_exit(self):
self.do_core_test('test_asyncify_during_exit.cpp', emcc_args=['-DNO_ASYNC'], out_suffix='_no_async')

@no_asan('asyncify stack operations confuse asan')
@no_lsan('undefined symbol __global_base')
@no_wasm2js('dynamic linking support in wasm2js')
def test_asyncify_main_module(self):
self.set_setting('ASYNCIFY', 1)
Expand All @@ -7741,7 +7754,7 @@ def test_emscripten_lazy_load_code(self, conditional):
second_size = os.path.getsize('emscripten_lazy_load_code.wasm.lazy.wasm')
print('first wasm size', first_size)
print('second wasm size', second_size)
if not conditional and self.is_optimizing() and '-g' not in self.emcc_args:
if not conditional and self.is_optimizing() and '-g' not in self.emcc_args and '-fsanitize=leak' not in self.emcc_args:
# If the call to lazy-load is unconditional, then the optimizer can dce
# out more than half
self.assertLess(first_size, 0.6 * second_size)
Expand Down Expand Up @@ -7806,6 +7819,7 @@ def verify_broken(args=['0']):

# Test basic wasm2js functionality in all core compilation modes.
@no_asan('no wasm2js support yet in asan')
@no_lsan('no wasm2js support yet in lsan')
def test_wasm2js(self):
if not self.is_wasm():
self.skipTest('redundant to test wasm2js in wasm2js* mode')
Expand All @@ -7821,6 +7835,7 @@ def test_wasm2js(self):
self.assertNotExists('test_hello_world.js.mem')

@no_asan('no wasm2js support yet in asan')
@no_lsan('no wasm2js support yet in lsan')
def test_maybe_wasm2js(self):
if not self.is_wasm():
self.skipTest('redundant to test wasm2js in wasm2js* mode')
Expand Down Expand Up @@ -7990,10 +8005,12 @@ def test_brk(self):
# Tests that we can use the dlmalloc mallinfo() function to obtain information
# about malloc()ed blocks and compute how much memory is used/freed.
@no_asan('mallinfo is not part of ASan malloc')
@no_lsan('mallinfo is not part of LSan malloc')
def test_mallinfo(self):
self.do_runf(test_file('mallinfo.cpp'), 'OK.')

@no_asan('cannot replace malloc/free with ASan')
@no_lsan('cannot replace malloc/free with LSan')
def test_wrap_malloc(self):
self.do_runf(test_file('wrap_malloc.cpp'), 'OK.')

Expand Down Expand Up @@ -8070,6 +8087,7 @@ def test_minimal_runtime_no_declare_asm_module_exports(self):
self.set_setting('WASM_ASYNC_COMPILATION', 0)
self.maybe_closure()
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
self.do_runf(test_file('declare_asm_module_exports.cpp'), 'jsFunction: 1')

# Tests that -s MINIMAL_RUNTIME=1 works well in different build modes
Expand All @@ -8095,6 +8113,7 @@ def test_minimal_runtime_hello_world(self, args):
@no_asan('TODO: ASan support in minimal runtime')
def test_minimal_runtime_hello_printf(self, extra_setting):
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
self.set_setting(extra_setting)
# $FS is not fully compatible with MINIMAL_RUNTIME so fails with closure
# compiler. lsan also pulls in $FS
Expand All @@ -8106,6 +8125,7 @@ def test_minimal_runtime_hello_printf(self, extra_setting):
@no_asan('TODO: ASan support in minimal runtime')
def test_minimal_runtime_safe_heap(self):
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
self.set_setting('SAFE_HEAP')
# $FS is not fully compatible with MINIMAL_RUNTIME so fails with closure
# compiler.
Expand All @@ -8118,6 +8138,7 @@ def test_minimal_runtime_safe_heap(self):
@no_asan('TODO: ASan support in minimal runtime')
def test_minimal_runtime_global_initializer(self):
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
self.maybe_closure()
self.do_runf(test_file('test_global_initializer.cpp'), 't1 > t0: 1')

Expand All @@ -8128,6 +8149,7 @@ def test_return_address(self):

@no_wasm2js('TODO: sanitizers in wasm2js')
@no_asan('-fsanitize-minimal-runtime cannot be used with ASan')
@no_lsan('-fsanitize-minimal-runtime cannot be used with LSan')
def test_ubsan_minimal_too_many_errors(self):
self.emcc_args += ['-fsanitize=undefined', '-fsanitize-minimal-runtime']
if not self.is_wasm():
Expand All @@ -8140,6 +8162,7 @@ def test_ubsan_minimal_too_many_errors(self):

@no_wasm2js('TODO: sanitizers in wasm2js')
@no_asan('-fsanitize-minimal-runtime cannot be used with ASan')
@no_lsan('-fsanitize-minimal-runtime cannot be used with LSan')
def test_ubsan_minimal_errors_same_place(self):
self.emcc_args += ['-fsanitize=undefined', '-fsanitize-minimal-runtime']
if not self.is_wasm():
Expand Down Expand Up @@ -8708,6 +8731,7 @@ def test_minimal_runtime_emscripten_get_exported_function(self):
# Could also test with -s ALLOW_TABLE_GROWTH=1
self.set_setting('RESERVED_FUNCTION_POINTERS', 2)
self.set_setting('MINIMAL_RUNTIME')
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
self.emcc_args += ['-lexports.js']
self.do_core_test('test_get_exported_function.cpp')

Expand Down
4 changes: 3 additions & 1 deletion tests/third_party/libiberty/cp-demangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -4220,7 +4220,9 @@ is_gnu_v3_mangled_dtor (const char *name)
int main(int argc, char **argv)
{
int status;
printf("*%s*\n", __cxa_demangle(argv[1], 0, 0, &status));
char* s = __cxa_demangle(argv[1], 0, 0, &status);
printf("*%s*\n", s);
free(s);
return 0;
}

7 changes: 3 additions & 4 deletions tools/system_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1746,14 +1746,13 @@ def add_library(libname):
add_library('libstandalonewasm')
add_library('libc_rt')

if settings.USE_LSAN:
force_include.append('liblsan_rt')
add_library('liblsan_rt')

if settings.USE_ASAN:
force_include.append('libasan_rt')
add_library('libasan_rt')
add_library('libasan_js')
elif settings.USE_LSAN:
force_include.append('liblsan_rt')
add_library('liblsan_rt')

if settings.UBSAN_RUNTIME == 1:
add_library('libubsan_minimal_rt')
Expand Down