Skip to content

Commit fde641c

Browse files
committed
Fix lsan test suite
With this change the entire `lsan` suite passes.
1 parent 0a2963a commit fde641c

File tree

5 files changed

+51
-23
lines changed

5 files changed

+51
-23
lines changed

system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
394394
#endif
395395

396396
#if SANITIZER_EMSCRIPTEN
397+
#define __ATTRP_C11_THREAD ((void*)(uptr)-1)
397398
extern "C" {
398399
int emscripten_builtin_pthread_create(void *thread, void *attr,
399400
void *(*callback)(void *), void *arg);
@@ -452,7 +453,7 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr,
452453
ENSURE_LSAN_INITED;
453454
EnsureMainThreadIDIsCorrect();
454455
__sanitizer_pthread_attr_t myattr;
455-
if (!attr) {
456+
if (!attr || attr == __ATTRP_C11_THREAD) {
456457
pthread_attr_init(&myattr);
457458
attr = &myattr;
458459
}

tests/core/test_dynamic_cast.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ struct Derived : Support {};
1616
int main() {
1717
Support* p = new Derived;
1818
dynamic_cast<Derived*>(p)->f();
19+
delete p;
20+
return 0;
1921
}

tests/test_core.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ def can_do_standalone(self):
182182
not self.get_setting('MINIMAL_RUNTIME') and \
183183
not self.get_setting('SAFE_HEAP') and \
184184
not self.get_setting('MEMORY64') and \
185-
'-fsanitize=address' not in self.emcc_args
185+
'-fsanitize=address' not in self.emcc_args and \
186+
'-fsanitize=leak' not in self.emcc_args
186187

187188

188189
def also_with_wasmfs(func):
@@ -660,6 +661,7 @@ def test_align64(self):
660661
''')
661662

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

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

@@ -1567,6 +1571,7 @@ def test_segfault(self):
15671571
15681572
struct Classey {
15691573
virtual void doIt() = 0;
1574+
virtual ~Classey() = default;
15701575
};
15711576
15721577
struct D1 : Classey {
@@ -1581,11 +1586,11 @@ def test_segfault(self):
15811586
return 0;
15821587
});
15831588
1584-
int main(int argc, char **argv)
1585-
{
1589+
int main(int argc, char **argv) {
15861590
Classey *p = argc == 100 ? new D1() : (Classey*)%s;
15871591
15881592
p->doIt();
1593+
delete p;
15891594
15901595
return 0;
15911596
}
@@ -1767,16 +1772,17 @@ def test_set_align(self):
17671772

17681773
self.do_core_test('test_set_align.c')
17691774

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

1775-
# test EXPORT_ALL
1776-
self.set_setting('EXPORTED_FUNCTIONS', [])
1777-
self.set_setting('EXPORT_ALL')
1778-
self.set_setting('LINKABLE')
1779-
self.do_core_test('test_emscripten_api.cpp')
1779+
# Sanitizers are not compatible with LINKABLE (dynamic linking.
1780+
if not is_sanitizing(self.emcc_args):
1781+
# test EXPORT_ALL
1782+
self.set_setting('EXPORTED_FUNCTIONS', [])
1783+
self.set_setting('EXPORT_ALL')
1784+
self.set_setting('LINKABLE')
1785+
self.do_core_test('test_emscripten_api.cpp')
17801786

17811787
def test_emscripten_run_script_string_int(self):
17821788
src = r'''
@@ -1921,7 +1927,6 @@ def test_em_asm_2(self):
19211927
# Tests various different ways to invoke the MAIN_THREAD_EM_ASM(), MAIN_THREAD_EM_ASM_INT() and MAIN_THREAD_EM_ASM_DOUBLE() macros.
19221928
# 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
19231929
# test cases are added to test_em_asm_2.cpp for EM_ASM, they will also get tested in MAIN_THREAD_EM_ASM form.
1924-
@no_asan('Cannot use ASan: test depends exactly on heap size')
19251930
def test_main_thread_em_asm(self):
19261931
src = read_file(test_file('core/test_em_asm_2.cpp'))
19271932
create_file('src.cpp', src.replace('EM_ASM', 'MAIN_THREAD_EM_ASM'))
@@ -1972,10 +1977,8 @@ def test_em_asm_direct(self):
19721977
'linked_c': (['-s', 'MAIN_MODULE'], True),
19731978
})
19741979
def test_em_js(self, args, force_c):
1975-
if 'MAIN_MODULE' in args and not self.is_wasm():
1976-
self.skipTest('main module support for non-wasm')
1977-
if '-fsanitize=address' in self.emcc_args:
1978-
self.skipTest('no dynamic library support in asan yet')
1980+
if 'MAIN_MODULE' in args:
1981+
self.check_dylink()
19791982
self.emcc_args += args + ['-s', 'EXPORTED_FUNCTIONS=_main,_malloc']
19801983

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

21182122
@no_wasm2js('no WebAssembly.Memory()')
21192123
@no_asan('ASan alters the memory size')
2124+
@no_lsan('LSan alters the memory size')
21202125
def test_module_wasm_memory(self):
21212126
self.emcc_args += ['--pre-js', test_file('core/test_module_wasm_memory.js')]
21222127
self.set_setting('IMPORTED_MEMORY')
@@ -2402,6 +2407,7 @@ def test_atexit(self):
24022407
self.set_setting('EXIT_RUNTIME')
24032408
self.do_core_test('test_atexit.c')
24042409

2410+
@no_lsan('https://github.com/emscripten-core/emscripten/issues/15988')
24052411
def test_atexit_threads_stub(self):
24062412
# also tests thread exit (__cxa_thread_atexit)
24072413
self.set_setting('EXIT_RUNTIME')
@@ -5288,6 +5294,7 @@ def test_utf8_invalid(self):
52885294
def test_minimal_runtime_utf8_invalid(self):
52895295
self.set_setting('EXPORTED_RUNTIME_METHODS', ['UTF8ToString', 'stringToUTF8'])
52905296
self.set_setting('MINIMAL_RUNTIME')
5297+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
52915298
for decoder_mode in [False, True]:
52925299
self.set_setting('TEXTDECODER', decoder_mode)
52935300
print(str(decoder_mode))
@@ -5845,6 +5852,7 @@ def test_whets(self):
58455852
# node is slower, and fail on 64-bit
58465853
@require_v8
58475854
@no_asan('depends on the specifics of memory size, which for asan we are forced to increase')
5855+
@no_lsan('depends on the specifics of memory size, which for lsan we are forced to increase')
58485856
def test_dlmalloc_inline(self):
58495857
# needed with typed arrays
58505858
self.set_setting('INITIAL_MEMORY', '128mb')
@@ -5856,6 +5864,7 @@ def test_dlmalloc_inline(self):
58565864
# node is slower, and fail on 64-bit
58575865
@require_v8
58585866
@no_asan('depends on the specifics of memory size, which for asan we are forced to increase')
5867+
@no_lsan('depends on the specifics of memory size, which for lsan we are forced to increase')
58595868
def test_dlmalloc(self):
58605869
# needed with typed arrays
58615870
self.set_setting('INITIAL_MEMORY', '128mb')
@@ -5887,11 +5896,13 @@ def test_dlmalloc(self):
58875896

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

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

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

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

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

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

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

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

@@ -8070,6 +8087,7 @@ def test_minimal_runtime_no_declare_asm_module_exports(self):
80708087
self.set_setting('WASM_ASYNC_COMPILATION', 0)
80718088
self.maybe_closure()
80728089
self.set_setting('MINIMAL_RUNTIME')
8090+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
80738091
self.do_runf(test_file('declare_asm_module_exports.cpp'), 'jsFunction: 1')
80748092

80758093
# Tests that -s MINIMAL_RUNTIME=1 works well in different build modes
@@ -8095,6 +8113,7 @@ def test_minimal_runtime_hello_world(self, args):
80958113
@no_asan('TODO: ASan support in minimal runtime')
80968114
def test_minimal_runtime_hello_printf(self, extra_setting):
80978115
self.set_setting('MINIMAL_RUNTIME')
8116+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
80988117
self.set_setting(extra_setting)
80998118
# $FS is not fully compatible with MINIMAL_RUNTIME so fails with closure
81008119
# compiler. lsan also pulls in $FS
@@ -8106,6 +8125,7 @@ def test_minimal_runtime_hello_printf(self, extra_setting):
81068125
@no_asan('TODO: ASan support in minimal runtime')
81078126
def test_minimal_runtime_safe_heap(self):
81088127
self.set_setting('MINIMAL_RUNTIME')
8128+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
81098129
self.set_setting('SAFE_HEAP')
81108130
# $FS is not fully compatible with MINIMAL_RUNTIME so fails with closure
81118131
# compiler.
@@ -8118,6 +8138,7 @@ def test_minimal_runtime_safe_heap(self):
81188138
@no_asan('TODO: ASan support in minimal runtime')
81198139
def test_minimal_runtime_global_initializer(self):
81208140
self.set_setting('MINIMAL_RUNTIME')
8141+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
81218142
self.maybe_closure()
81228143
self.do_runf(test_file('test_global_initializer.cpp'), 't1 > t0: 1')
81238144

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

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

81418163
@no_wasm2js('TODO: sanitizers in wasm2js')
81428164
@no_asan('-fsanitize-minimal-runtime cannot be used with ASan')
8165+
@no_lsan('-fsanitize-minimal-runtime cannot be used with LSan')
81438166
def test_ubsan_minimal_errors_same_place(self):
81448167
self.emcc_args += ['-fsanitize=undefined', '-fsanitize-minimal-runtime']
81458168
if not self.is_wasm():
@@ -8708,6 +8731,7 @@ def test_minimal_runtime_emscripten_get_exported_function(self):
87088731
# Could also test with -s ALLOW_TABLE_GROWTH=1
87098732
self.set_setting('RESERVED_FUNCTION_POINTERS', 2)
87108733
self.set_setting('MINIMAL_RUNTIME')
8734+
self.emcc_args += ['--pre-js', test_file('minimal_runtime_exit_handling.js')]
87118735
self.emcc_args += ['-lexports.js']
87128736
self.do_core_test('test_get_exported_function.cpp')
87138737

tests/third_party/libiberty/cp-demangle.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4220,7 +4220,9 @@ is_gnu_v3_mangled_dtor (const char *name)
42204220
int main(int argc, char **argv)
42214221
{
42224222
int status;
4223-
printf("*%s*\n", __cxa_demangle(argv[1], 0, 0, &status));
4223+
char* s = __cxa_demangle(argv[1], 0, 0, &status);
4224+
printf("*%s*\n", s);
4225+
free(s);
42244226
return 0;
42254227
}
42264228

tools/system_libs.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,14 +1746,13 @@ def add_library(libname):
17461746
add_library('libstandalonewasm')
17471747
add_library('libc_rt')
17481748

1749-
if settings.USE_LSAN:
1750-
force_include.append('liblsan_rt')
1751-
add_library('liblsan_rt')
1752-
17531749
if settings.USE_ASAN:
17541750
force_include.append('libasan_rt')
17551751
add_library('libasan_rt')
17561752
add_library('libasan_js')
1753+
elif settings.USE_LSAN:
1754+
force_include.append('liblsan_rt')
1755+
add_library('liblsan_rt')
17571756

17581757
if settings.UBSAN_RUNTIME == 1:
17591758
add_library('libubsan_minimal_rt')

0 commit comments

Comments
 (0)