-
Notifications
You must be signed in to change notification settings - Fork 77
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
Regression: Can't use the MPS with clang -fsanitize=address #204
Comments
It looks like the regression was introduced by me in 2b10812 |
im also getting a similar error when using asan with the thread stacks the config variant is this happens for both 0x7FFFFF7FF000 and 0x7FFFFFFFF000 when used as thread markers related to #210 (im using boem to obtain the appropiate stack top/bottom for me) ==637141==AddressSanitizer: failed to intercept '__isoc99_printf'
==637141==AddressSanitizer: failed to intercept '__isoc99_sprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_snprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_fprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_vprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_vsprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_vsnprintf'
==637141==AddressSanitizer: failed to intercept '__isoc99_vfprintf'
==637141==AddressSanitizer: failed to intercept 'xdr_destroy'
==637141==AddressSanitizer: failed to intercept 'crypt'
==637141==AddressSanitizer: failed to intercept 'crypt_r'
==637141==AddressSanitizer: failed to intercept '__cxa_rethrow_primary_exception'
==637141==AddressSanitizer: libc interceptors initialized
|| `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
|| `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
|| `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap ||
|| `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
|| `[0x000000000000, 0x00007fff7fff]` || LowMem ||
MemToShadow(shadow): 0x00008fff7000 0x000091ff6dff 0x004091ff6e00 0x02008fff6fff
redzone=16
max_redzone=2048
quarantine_size_mb=256M
thread_local_quarantine_size_kb=1024K
malloc_context_size=30
SHADOW_SCALE: 3
SHADOW_GRANULARITY: 8
SHADOW_OFFSET: 0x7fff8000
==637141==Installed the sigaction for signal 11
==637141==Installed the sigaction for signal 7
==637141==Installed the sigaction for signal 8
==637141==T0: FakeStack created: 0x7ffff63c3000 -- 0x7ffff6ecc000 stack_size_log: 20; mmapped 11300K, noreserve=0
==637141==T0: stack [0x7fffff7ff000,0x7ffffffff000) size 0x800000; local=0x7fffffffdd54
==637141==AddressSanitizer Init done
// ...
Process 637141 stopped
* thread #1, name = 'managed_object_', stop reason = signal SIGSEGV: invalid address (fault address: 0x7ffffffff000)
frame #0: 0x000000000081d0da managed_object_tests_debug`MANAGED_STACK_ADDRESS_BOEHM_GC_find_limit_with_bound(p="\U00000010\xcc\xff\xff\xff\U0000007f", up=1, bound=<no value available>) at os_dep.c:1007:54
1004 }
1005 result -= MIN_PAGE_SIZE; /* no underflow expected */
1006 }
-> 1007 MANAGED_STACK_ADDRESS_BOEHM_GC_noop1((word)(*result));
1008 }
1009 }
1010 MANAGED_STACK_ADDRESS_BOEHM_GC_reset_fault_handler();
(lldb) c
Process 637141 resuming
Primordial thread stack bottom: 0x7ffffffff000
deinit
deinit - collect
=================================================================
==637141==ERROR: AddressSanitizer: stack-use-after-return on address 0x7ffff6468360 at pc 0x00000064667a bp 0x7fffffffb650 sp 0x7fffffffb648
READ of size 8 at 0x7ffff6468360 thread T0
#0 0x646679 in mps_scan_area_tagged /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/scan.c:112:3
#1 0x6cdcd7 in TraceScanArea /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1566:10
#2 0x75ebdb in StackScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/ss.c:68:10
#3 0x6dc12c in ThreadScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/thix.c:264:11
#4 0x6db44c in RootScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/root.c:577:11
#5 0x7ea6a7 in traceScanRootRes /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:528:9
#6 0x7ea478 in traceScanRoot /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:545:9
#7 0x7ea402 in rootFlip /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:580:11
#8 0x6d0cec in RootsIterate /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/root.c:665:11
#9 0x6d1c5b in traceFlip /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:652:11
#10 0x6cffc1 in TraceStart /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1694:10
#11 0x6945ca in TraceStartCollectAll /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1794:9
#12 0x626dfa in ArenaStartCollect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/traceanc.c:634:9
#13 0x6272e6 in ArenaCollect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/traceanc.c:652:9
#14 0x6270fd in mps_arena_collect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/mpsi.c:313:11
#15 0x81c49a in managed_obj_collect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/src/managed_object_obj.c:509:5
#16 0x81c6ba in managed_obj_deinit /home/DATA/git/Gecko/HTML/qparse/ManagedObject/src/managed_object_obj.c:525:5
#17 0x4db875 in MPS_0_Test::TestBody() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/tests/managed_object_tests.cpp:251:5
#18 0x5c700c in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2612:10
#19 0x5789f8 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2648:14
#20 0x5249c8 in testing::Test::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2687:5
#21 0x52684d in testing::TestInfo::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2836:11
#22 0x528068 in testing::TestSuite::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:3015:30
#23 0x54b6e2 in testing::internal::UnitTestImpl::RunAllTests() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:5921:44
#24 0x5d807c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2612:10
#25 0x57f3b8 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2648:14
#26 0x54ab16 in testing::UnitTest::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:5485:10
#27 0x4ee510 in RUN_ALL_TESTS() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/include/gtest/gtest.h:2316:73
#28 0x4ee49f in main /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest_main.cc:64:10
#29 0x7ffff7a4fd09 in __libc_start_main csu/../csu/libc-start.c:308:16
#30 0x429ac9 in _start (/home/DATA/git/Gecko/HTML/qparse/ManagedObject/debug_asan_EXECUTABLE/managed_object_tests_debug+0x429ac9)
Address 0x7ffff6468360 is located in stack of thread T0 at offset 32 in frame
#0 0x625f7f in StackHot /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/ss.c:37
This frame has 1 object(s):
[32, 40) 'stackOut.addr' <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/scan.c:112:3 in mps_scan_area_tagged
Shadow bytes around the buggy address:
0x10007ec85010: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85020: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85030: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85040: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85050: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x10007ec85060: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5
0x10007ec85070: f1 f1 f1 f1 00 f3 f3 f3 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85080: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85090: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec850a0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec850b0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==637141==ABORTING
(lldb) AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.
Process 637141 stopped
* thread #1, name = 'managed_object_', stop reason = Use of stack memory after return
frame #0: 0x00000000004adcb0 managed_object_tests_debug`__asan::AsanDie()
managed_object_tests_debug`__asan::AsanDie:
-> 0x4adcb0 <+0>: pushq %rbx
0x4adcb1 <+1>: lock
0x4adcb2 <+2>: addl $0x1, 0x50a8e3(%rip)
0x4adcb9 <+9>: movq $0xa495c8, %rax ; imm = 0xA495C8
(lldb) up
frame #1: 0x00000000004c30fc managed_object_tests_debug`__sanitizer::Die() + 172
managed_object_tests_debug`__sanitizer::Die:
-> 0x4c30fc <+172>: movq $0xa495c8, %rax ; imm = 0xA495C8
0x4c3103 <+179>: cmpb $0x0, 0xf8(%rax)
0x4c310a <+186>: je 0x4c30a9 ; <+89>
0x4c310c <+188>: callq 0x4c4df0 ; __sanitizer::Abort()
(lldb)
frame #2: 0x00000000004aa201 managed_object_tests_debug`__asan::ScopedInErrorReport::~ScopedInErrorReport() + 449
-> 0x4aa201: nopw %cs:(%rax,%rax)
0x4aa20b: nopl (%rax,%rax)
managed_object_tests_debug`__asan::ReportDoubleFree:
0x4aa210 <+0>: pushq %r14
0x4aa212 <+2>: pushq %rbx
(lldb)
frame #3: 0x00000000004abd46 managed_object_tests_debug`__asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) + 1462
managed_object_tests_debug`__asan::ReportGenericError:
-> 0x4abd46 <+1462>: addq $0xc18, %rsp ; imm = 0xC18
0x4abd4d <+1469>: popq %rbx
0x4abd4e <+1470>: popq %r12
0x4abd50 <+1472>: popq %r13
(lldb)
frame #4: 0x00000000004ac5b8 managed_object_tests_debug`__asan_report_load8 + 40
managed_object_tests_debug`__asan_report_load8:
-> 0x4ac5b8 <+40>: addq $0x20, %rsp
0x4ac5bc <+44>: popq %rbp
0x4ac5bd <+45>: retq
0x4ac5be: nop
(lldb)
frame #5: 0x000000000064667a managed_object_tests_debug`mps_scan_area_tagged(ss=0x00007ffff66e8a28, base=0x00007ffff6468360, limit=0x00007ffffffff000, closure=0x00007ffff3732a68) at scan.c:112:3
109 mps_word_t mask = tag->mask;
110 mps_word_t pattern = tag->pattern;
111
-> 112 MPS_SCAN_AREA(tag_bits == pattern);
113
114 return MPS_RES_OK;
115 }
(lldb) ==637849==T0: FakeStack created: 0x7ffff63c3000 -- 0x7ffff6ecc000 stack_size_log: 20; mmapped 11300K, noreserve=0
==637849==T0: stack [0x7fffff7ff000,0x7ffffffff000) size 0x800000; local=0x7fffffffdd54
// ...
Process 637849 resuming
Primordial thread stack bottom: 0x7fffff7ff000
deinit
deinit - collect
=================================================================
==637849==ERROR: AddressSanitizer: stack-use-after-return on address 0x7ffff6468360 at pc 0x00000064667a bp 0x7fffffffb650 sp 0x7fffffffb648
READ of size 8 at 0x7ffff6468360 thread T0
#0 0x646679 in mps_scan_area_tagged /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/scan.c:112:3
#1 0x6cdcd7 in TraceScanArea /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1566:10
#2 0x75ebdb in StackScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/ss.c:68:10
#3 0x6dc12c in ThreadScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/thix.c:264:11
#4 0x6db44c in RootScan /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/root.c:577:11
#5 0x7ea6a7 in traceScanRootRes /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:528:9
#6 0x7ea478 in traceScanRoot /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:545:9
#7 0x7ea402 in rootFlip /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:580:11
#8 0x6d0cec in RootsIterate /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/root.c:665:11
#9 0x6d1c5b in traceFlip /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:652:11
#10 0x6cffc1 in TraceStart /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1694:10
#11 0x6945ca in TraceStartCollectAll /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/trace.c:1794:9
#12 0x626dfa in ArenaStartCollect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/traceanc.c:634:9
#13 0x6272e6 in ArenaCollect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/traceanc.c:652:9
#14 0x6270fd in mps_arena_collect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/mpsi.c:313:11
#15 0x81c49a in managed_obj_collect /home/DATA/git/Gecko/HTML/qparse/ManagedObject/src/managed_object_obj.c:509:5
#16 0x81c6ba in managed_obj_deinit /home/DATA/git/Gecko/HTML/qparse/ManagedObject/src/managed_object_obj.c:525:5
#17 0x4db875 in MPS_0_Test::TestBody() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/tests/managed_object_tests.cpp:251:5
#18 0x5c700c in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2612:10
#19 0x5789f8 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2648:14
#20 0x5249c8 in testing::Test::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2687:5
#21 0x52684d in testing::TestInfo::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2836:11
#22 0x528068 in testing::TestSuite::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:3015:30
#23 0x54b6e2 in testing::internal::UnitTestImpl::RunAllTests() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:5921:44
#24 0x5d807c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2612:10
#25 0x57f3b8 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:2648:14
#26 0x54ab16 in testing::UnitTest::Run() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest.cc:5485:10
#27 0x4ee510 in RUN_ALL_TESTS() /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/include/gtest/gtest.h:2316:73
#28 0x4ee49f in main /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest_main.cc:64:10
#29 0x7ffff7a4fd09 in __libc_start_main csu/../csu/libc-start.c:308:16
#30 0x429ac9 in _start (/home/DATA/git/Gecko/HTML/qparse/ManagedObject/debug_asan_EXECUTABLE/managed_object_tests_debug+0x429ac9)
Address 0x7ffff6468360 is located in stack of thread T0 at offset 32 in frame
#0 0x625f7f in StackHot /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/ss.c:37
This frame has 1 object(s):
[32, 40) 'stackOut.addr' <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-return /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/scan.c:112:3 in mps_scan_area_tagged
Shadow bytes around the buggy address:
0x10007ec85010: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85020: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85030: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85040: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85050: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
=>0x10007ec85060: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5[f5]f5 f5 f5
0x10007ec85070: f1 f1 f1 f1 00 f3 f3 f3 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85080: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec85090: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec850a0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x10007ec850b0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==637849==ABORTING
(lldb)
frame #5: 0x000000000064667a managed_object_tests_debug`mps_scan_area_tagged(ss=0x00007ffff66e8a28, base=0x00007ffff6468360, limit=0x00007fffff7ff000, closure=0x00007ffff3732a68) at scan.c:112:3
109 mps_word_t mask = tag->mask;
110 mps_word_t pattern = tag->pattern;
111
-> 112 MPS_SCAN_AREA(tag_bits == pattern);
113
114 return MPS_RES_OK;
115 }
(lldb)
|
specifically we seem to be attempting to scan an (in which however it appears to be OUTSIDE of the reported stack bounds (by both asan and boem) 0x7ffff63c3000 <- asan FakeStack begin
0x7ffff6468360 <- address being scanned, Stack-Use-After-Return
0x7ffff68cd820 <- &state // ::TestBody(this=0x0000602000000690) // TEST(MPS, 0) { ManagedObjState state;
0x7ffff6ecc000 <- asan FakeStack end
0x7fffff7ff000 <- stack begin
0x7fffffffde28 <- argv // main(argc=1, argv=0x00007fffffffde28)
0x7ffffffff000 <- stack end (lldb) target list
Current targets:
* target #0: /home/DATA/git/Gecko/HTML/qparse/ManagedObject/debug_asan_EXECUTABLE/managed_object_tests_debug ( arch=x86_64-pc-linux-gnu, platform=host, pid=638376, state=stopped )
(lldb) shell cat /proc/638376/maps
// ...
00996000-0135f000 rw-p 00000000 00:00 0 [heap]
// ...
7ffff626f000-7ffff6eda000 rw-p 00000000 00:00 0 // within range of asan FakeStack
// ...
7fffff7ff000-7ffffffff000 rw-p 00000000 00:00 0 [stack] // reported stack
(lldb) i do not know how to avoid this |
a work around seems to be explicitly disabling ASAN instrumentation in the scan.c functions /* scan.c: SCANNING FUNCTIONS
*
* $Id$
* Copyright (c) 2001-2020 Ravenbrook Limited.
* See end of file for license.
*
* .outside: The code in this file is written as if *outside* the MPS,
* and so is restricted to facilities in the MPS interface. MPS users
* are invited to read this code and use it as a basis for their own
* scanners. See topic "Area Scanners" in the MPS manual.
*
* TODO: Design document.
*/
#include "mps.h"
#include "mpstd.h" /* for MPS_BUILD_MV */
#ifdef MPS_BUILD_MV
/* MSVC warning 4127 = conditional expression is constant */
/* Objects to: MPS_SCAN_AREA(1). */
#pragma warning( disable : 4127 )
#endif
#define MPS_SCAN_AREA(test) \
MPS_SCAN_BEGIN(ss) { \
mps_word_t *p = base; \
while (p < (mps_word_t *)limit) { \
mps_word_t word = *p; \
mps_word_t tag_bits = word & mask; \
if (test) { \
mps_addr_t ref = (mps_addr_t)(word ^ tag_bits); \
if (MPS_FIX1(ss, ref)) { \
mps_res_t res = MPS_FIX2(ss, &ref); \
if (res != MPS_RES_OK) \
return res; \
*p = (mps_word_t)ref | tag_bits; \
} \
} \
++p; \
} \
} MPS_SCAN_END(ss);
/* support asan */
#if defined(__has_feature)
/* __has_feature() is supported. */
# if __has_feature(address_sanitizer)
# define ADDRESS_SANITIZER
# endif
# if __has_feature(memory_sanitizer)
# define MEMORY_SANITIZER
# endif
# if __has_feature(thread_sanitizer)
# define THREAD_SANITIZER
# endif
#else
# ifdef __SANITIZE_ADDRESS__
/* GCC v4.8+ */
# define ADDRESS_SANITIZER
# endif
# if defined(__SANITIZE_THREAD__)
/* GCC v7.1+ */
# define THREAD_SANITIZER
# endif
#endif /* !__has_feature */
/* Convenient internal macro to test version of Clang. */
#if defined(__clang__) && defined(__clang_major__)
# define MPS_GC_CLANG_PREREQ(major, minor) \
((__clang_major__ << 8) + __clang_minor__ >= ((major) << 8) + (minor))
# define MPS_GC_CLANG_PREREQ_FULL(major, minor, patchlevel) \
(MPS_GC_CLANG_PREREQ(major, (minor) + 1) \
|| (__clang_major__ == (major) && __clang_minor__ == (minor) \
&& __clang_patchlevel__ >= (patchlevel)))
#else
# define MPS_GC_CLANG_PREREQ(major, minor) 0 /* FALSE */
# define MPS_GC_CLANG_PREREQ_FULL(major, minor, patchlevel) 0
#endif
/* Convenient internal macro to test version of gcc. */
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define MPS_GC_GNUC_PREREQ(major, minor) \
((__GNUC__ << 8) + __GNUC_MINOR__ >= ((major) << 8) + (minor))
#else
# define MPS_GC_GNUC_PREREQ(major, minor) 0 /* FALSE */
#endif
#ifndef MPS_GC_ATTR_NOINLINE
# if MPS_GC_GNUC_PREREQ(4, 0)
# define MPS_GC_ATTR_NOINLINE __attribute__((__noinline__))
# elif _MSC_VER >= 1400
# define MPS_GC_ATTR_NOINLINE __declspec(noinline)
# else
# define MPS_GC_ATTR_NOINLINE /* empty */
# endif
#endif
#ifndef MPS_GC_ATTR_NO_SANITIZE_ADDR
# ifndef ADDRESS_SANITIZER
# define MPS_GC_ATTR_NO_SANITIZE_ADDR /* empty */
# elif MPS_GC_CLANG_PREREQ(3, 8)
# define MPS_GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize("address")))
# else
# define MPS_GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize_address))
# endif
#endif /* !MPS_GC_ATTR_NO_SANITIZE_ADDR */
#ifndef MPS_GC_ATTR_NO_SANITIZE_MEMORY
# ifndef MEMORY_SANITIZER
# define MPS_GC_ATTR_NO_SANITIZE_MEMORY /* empty */
# elif MPS_GC_CLANG_PREREQ(3, 8)
# define MPS_GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
# else
# define MPS_GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
# endif
#endif /* !MPS_GC_ATTR_NO_SANITIZE_MEMORY */
#ifndef MPS_GC_ATTR_NO_SANITIZE_THREAD
# ifndef THREAD_SANITIZER
# define MPS_GC_ATTR_NO_SANITIZE_THREAD /* empty */
# elif MPS_GC_CLANG_PREREQ(3, 8)
# define MPS_GC_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
# else
/* It seems that no_sanitize_thread attribute has no effect if the */
/* function is inlined (as of gcc 11.1.0, at least). */
# define MPS_GC_ATTR_NO_SANITIZE_THREAD \
MPS_GC_ATTR_NOINLINE __attribute__((no_sanitize_thread))
# endif
#endif /* !MPS_GC_ATTR_NO_SANITIZE_THREAD */
/* mps_scan_area -- scan contiguous area of references
*
* This is a convenience function for scanning the contiguous area
* [base, limit). I.e., it calls Fix on all words from base up to
* limit, inclusive of base and exclusive of limit.
*
* This scanner is appropriate for use when all words in the area are
* simple untagged references.
*/
MPS_GC_ATTR_NO_SANITIZE_ADDR
MPS_GC_ATTR_NO_SANITIZE_MEMORY
MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area(mps_ss_t ss,
void *base, void *limit,
void *closure)
{
mps_word_t mask = 0;
(void)closure; /* unused */
MPS_SCAN_AREA(1);
return MPS_RES_OK;
}
/* mps_scan_area_masked -- scan area masking off tag bits
*
* Like mps_scan_area, but removes tag bits before fixing references,
* and restores them afterwards.
*
* For example, if mask is 7, then this scanner will clear the bottom
* three bits of each word before fixing.
*
* This scanner is useful when all words in the area must be treated
* as references no matter what tag they have.
*/
MPS_GC_ATTR_NO_SANITIZE_ADDR
MPS_GC_ATTR_NO_SANITIZE_MEMORY
MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_masked(mps_ss_t ss,
void *base, void *limit,
void *closure)
{
mps_scan_tag_t tag = closure;
mps_word_t mask = tag->mask;
MPS_SCAN_AREA(1);
return MPS_RES_OK;
}
/* mps_scan_area_tagged -- scan area selecting by tag
*
* Like mps_scan_area_masked, except only references whose masked bits
* match a particular tag pattern are fixed.
*
* For example, if mask is 7 and pattern is 5, then this scanner will
* only fix words whose low order bits are 0b101.
*/
MPS_GC_ATTR_NO_SANITIZE_ADDR
MPS_GC_ATTR_NO_SANITIZE_MEMORY
MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_tagged(mps_ss_t ss,
void *base, void *limit,
void *closure)
{
mps_scan_tag_t tag = closure;
mps_word_t mask = tag->mask;
mps_word_t pattern = tag->pattern;
MPS_SCAN_AREA(tag_bits == pattern);
return MPS_RES_OK;
}
/* mps_scan_area_tagged_or_zero -- scan area selecting by tag or zero
*
* Like mps_scan_area_tagged, except references whose masked bits are
* zero are fixed in addition to those that match the pattern.
*
* For example, if mask is 7 and pattern is 3, then this scanner will
* fix words whose low order bits are 0b011 and words whose low order
* bits are 0b000, but not any others.
*
* This scanner is most useful for ambiguously scanning the stack and
* registers when using an optimising C compiler and non-zero tags on
* references, since the compiler is likely to leave untagged
* addresses of objects around which must not be ignored.
*/
MPS_GC_ATTR_NO_SANITIZE_ADDR
MPS_GC_ATTR_NO_SANITIZE_MEMORY
MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_tagged_or_zero(mps_ss_t ss,
void *base, void *limit,
void *closure)
{
mps_scan_tag_t tag = closure;
mps_word_t mask = tag->mask;
mps_word_t pattern = tag->pattern;
MPS_SCAN_AREA(tag_bits == 0 || tag_bits == pattern);
return MPS_RES_OK;
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2020 Ravenbrook Limited <https://www.ravenbrook.com/>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ |
however we then get a prot crash in asan which does not happen under a non-asan build Process 642086 stopped
* thread #1, name = 'managed_object_', stop reason = signal SIGSEGV: address access protected (fault address: 0x7ffff6eda000)
frame #0: 0x00000000006461b2 managed_object_tests_debug`mps_scan_area_tagged(ss=0x00007ffff66e8a28, base=0x00007ffff6468360, limit=0x00007ffffffff000, closure=0x00007ffff3732a68) at scan.c:190:3
187 mps_word_t mask = tag->mask;
188 mps_word_t pattern = tag->pattern;
189
-> 190 MPS_SCAN_AREA(tag_bits == pattern);
191
192 return MPS_RES_OK;
193 }
(lldb) s
This version of LLDB has no plugin for the language "assembler". Inspection of frame variables will be limited.
Process 642086 stopped
* thread #1, name = 'managed_object_', stop reason = unknown crash reason
frame #0: 0x00007ffff7a65087 libc.so.6`kill at syscall-template.S:120
(lldb)
AddressSanitizer:DEADLYSIGNAL
=================================================================
==642086==ERROR: AddressSanitizer: SEGV on unknown address 0x03e80009cc26 (pc 0x7ffff7a65087 bp 0x7fffffffb270 sp 0x7fffffffb158 T0)
==642086==The signal is caused by a READ memory access.
#0 0x7ffff7a65087 in kill signal/../sysdeps/unix/syscall-template.S:120
#1 0x7dc01c in sigHandle /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/protsgix.c:114:9
#2 0x7ffff7a64d5f (/lib/x86_64-linux-gnu/libc.so.6+0x38d5f)
#3 0x6461b1 in mps_scan_area_tagged /home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/scan.c:190:3 additionally i have discovered that boehm was incorrectly restoring MPS's signal handler via this is fixable via defining HOWEVER we then go on to get a re-entrent arena lock ( frame #2: 0x0000000000817eae managed_object_tests_debug`mps_lib_assert_fail_default(file="/home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/lockix.c", line=126, condition="res == 0") at mpsliban.c:78:3
frame #3: 0x0000000000622de8 managed_object_tests_debug`mps_lib_assert_fail(file="/home/DATA/git/Gecko/HTML/qparse/ManagedObject/mps/code/lockix.c", line=126, condition="res == 0") at mpsliban.c:87:3
frame #4: 0x000000000068fa1d managed_object_tests_debug`LockClaim(lock=0x00007ffff3732110) at lockix.c:126:3
frame #5: 0x000000000068f5b2 managed_object_tests_debug`ArenaEnterLock(arena=0x00007ffff626e000, recursive=0) at global.c:576:5
frame #6: 0x0000000000622db7 managed_object_tests_debug`ArenaEnter(arena=0x00007ffff626e000) at global.c:553:3
frame #7: 0x00000000006907b4 managed_object_tests_debug`ArenaAccess(addr=0x00007ffff6eda000, mode=3, context=0x00007ffff67d4e40) at global.c:655:5
frame #8: 0x00000000007dc03e managed_object_tests_debug`sigHandle(sig=11, info=0x00007fffffffb3b0, uap=0x00007fffffffb280) at protsgix.c:97:11
frame #9: 0x00007ffff7f9b140 libpthread.so.0`__restore_rt
frame #10: 0x0000000000646412 managed_object_tests_debug`mps_scan_area_tagged(ss=0x00007ffff66e8a28, base=0x00007ffff6468360, limit=0x00007ffffffff000, closure=0x00007ffff3732a68) at scan.c:210:3
frame #11: 0x00000000006cd928 managed_object_tests_debug`TraceScanArea(ss=0x00007ffff66e8a20, base=0x00007ffff6468360, limit=0x00007ffffffff000, scan_area=(managed_object_tests_debug`mps_scan_area_tagged at scan.c:205), closure=0x00007ffff3732a68) at trace.c:1566:10
frame #12: 0x000000000075e1fc managed_object_tests_debug`StackScan(ss=0x00007ffff66e8a20, stackCold=0x00007ffffffff000, scan_area=(managed_object_tests_debug`mps_scan_area_tagged at scan.c:205), closure=0x00007ffff3732a68) at ss.c:68:10
frame #13: 0x00000000006db74d managed_object_tests_debug`ThreadScan(ss=0x00007ffff66e8a20, thread=0x00007ffff3732988, stackCold=0x00007ffffffff000, scan_area=(managed_object_tests_debug`mps_scan_area_tagged at scan.c:205), closure=0x00007ffff3732a68) at thix.c:264:11
frame #14: 0x00000000006daa6d managed_object_tests_debug`RootScan(ss=0x00007ffff66e8a20, root=0x00007ffff3732a00) at root.c:577:11
frame #15: 0x00000000007e9cc8 managed_object_tests_debug`traceScanRootRes(ts=1, rank=0, arena=0x00007ffff626e000, root=0x00007ffff3732a00) at trace.c:528:9
frame #16: 0x00000000007e9a99 managed_object_tests_debug`traceScanRoot(ts=1, rank=0, arena=0x00007ffff626e000, root=0x00007ffff3732a00) at trace.c:545:9
frame #17: 0x00000000007e9a23 managed_object_tests_debug`rootFlip(root=0x00007ffff3732a00, p=0x00007ffff64fb120) at trace.c:580:11
frame #18: 0x00000000006d093d managed_object_tests_debug`RootsIterate(arena=0x00007ffff626e008, f=(managed_object_tests_debug`rootFlip at trace.c:567), p=0x00007ffff64fb120) at root.c:665:11
frame #19: 0x00000000006d18ac managed_object_tests_debug`traceFlip(trace=0x00007ffff626eb50) at trace.c:652:11
frame #20: 0x00000000006cfc12 managed_object_tests_debug`TraceStart(trace=0x00007ffff626eb50, mortality=0.84999999999999998, finishingTime=33402520) at trace.c:1694:10
frame #21: 0x000000000069421b managed_object_tests_debug`TraceStartCollectAll(traceReturn=0x00007ffff64683a0, arena=0x00007ffff626e000, why=4) at trace.c:1794:9
frame #22: 0x000000000062705b managed_object_tests_debug`ArenaStartCollect(globals=0x00007ffff626e008, why=4) at traceanc.c:634:9
frame #23: 0x0000000000627547 managed_object_tests_debug`ArenaCollect(globals=0x00007ffff626e008, why=4) at traceanc.c:652:9
frame #24: 0x000000000062735e managed_object_tests_debug`mps_arena_collect(arena=0x00007ffff626e000) at mpsi.c:313:11
frame #25: 0x000000000081bb5b managed_object_tests_debug`managed_obj_collect(state=0x00007ffff68cd820) at managed_object_obj.c:509:5 frame #4: 0x000000000068fa1d managed_object_tests_debug`LockClaim(lock=0x00007ffff3732110) at lockix.c:126:3
123
124 res = pthread_mutex_lock(&lock->mut);
125 /* pthread_mutex_lock will error if we own the lock already. */
-> 126 AVER(res == 0); /* <design/check/#.common> */
127
128 /* This should be the first claim. Now we own the mutex */
129 /* it is ok to check this. */
(lldb) up
frame #5: 0x000000000068f5b2 managed_object_tests_debug`ArenaEnterLock(arena=0x00007ffff626e000, recursive=0) at global.c:576:5
573 if(recursive) {
574 LockClaimRecursive(lock);
575 } else {
-> 576 LockClaim(lock);
577 }
578 AVERT(Arena, arena); /* can't AVERT it until we've got the lock */
579 if(recursive) {
(lldb)
frame #6: 0x0000000000622db7 managed_object_tests_debug`ArenaEnter(arena=0x00007ffff626e000) at global.c:553:3
550
551 void ArenaEnter(Arena arena)
552 {
-> 553 ArenaEnterLock(arena, FALSE);
554 }
555
556 /* The recursive argument specifies whether to claim the lock
(lldb)
frame #7: 0x00000000006907b4 managed_object_tests_debug`ArenaAccess(addr=0x00007ffff6eda000, mode=3, context=0x00007ffff67d4e40) at global.c:655:5
652 Arena arena = GlobalsArena(arenaGlobals);
653 Root root;
654
-> 655 ArenaEnter(arena); /* <design/arena#.lock.arena> */
656 EVENT3(ArenaAccessBegin, arena, addr, mode);
657
658 /* @@@@ The code below assumes that Roots and Segs are disjoint. */
(lldb)
frame #8: 0x00000000007dc03e managed_object_tests_debug`sigHandle(sig=11, info=0x00007fffffffb3b0, uap=0x00007fffffffb280) at protsgix.c:97:11
94
95 /* Offer each protection structure the opportunity to handle the */
96 /* exception. If it succeeds, then allow the mutator to continue. */
-> 97 if (ArenaAccess(base, mode, &context))
98 goto done;
99 }
100
(lldb) if we check the lock when in asan #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER)
// ASAN in use, duplicate code path to reduce the number of branches for conditional LockIsHeld statements
// ASAN in use, check if we are locked, this may happen if we fault on a protected page in asan
// while scanning the stack, at which point
// we already have a lock, we faulted while scanning, we must recover without locking
if (ArenaBusy(arena)) { we discover that when looking in the maps, the address which has been set to PROT_NONE
additionally keeping in mind this ONLY happens in ASAN (fsanitise), outside of ASAN everything works normally |
it appears that both malloc and mmap return memory pointing to the fake stack |
this is our current manually computed memory mapping 0x7ffff3700000 <- mmap
0x7ffff3780948 <- last reserved pointer before collect
0x7ffff620a010 <- malloc
0x7ffff6270000 <- mmap
0x7ffff6270000 <- arena
0x7ffff6270d50 <- &arena->stackWarm
0x7ffff6270d50 <- 1 StackHot(stackOut=0x00007ffff6270d50)
0x7ffff6270d50 <- 2 StackHot(stackOut=0x00007ffff6270d50)
0x7ffff63c3000 <- fake stack
0x7ffff63c3000 <- stackCold
0x7ffff63e9060 <- 1 &stackOut
0x7ffff6468320 <- 2 &stackOut
0x7ffff6468320 <- arena->stackWarm
0x7ffff6468320 <- warmest
0x7ffff6ecc000 <- fake stack assert(warmest < stackCold) // fails |
if we scan the real stack instead then we seem to not be able to pick up memory allocations correctly in an asan build |
so, in regards to #259 scanning the real stack, combined with forcefully reclaiming all references upon shutdown, works
testing debug_asan_EXECUTABLE/managed_object_tests_debug...
/* ... */
debug_asan_EXECUTABLE/managed_object_tests_debug returned with code 0
testing debug_asan_EXECUTABLE/managed_object_tests_no_debug...
==137580==AddressSanitizer: failed to intercept '__isoc99_printf'
==137580==AddressSanitizer: failed to intercept '__isoc99_sprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_snprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_fprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_vprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_vsprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_vsnprintf'
==137580==AddressSanitizer: failed to intercept '__isoc99_vfprintf'
==137580==AddressSanitizer: failed to intercept 'xdr_destroy'
==137580==AddressSanitizer: failed to intercept 'crypt'
==137580==AddressSanitizer: failed to intercept 'crypt_r'
==137580==AddressSanitizer: failed to intercept '__cxa_rethrow_primary_exception'
==137580==AddressSanitizer: libc interceptors initialized
|| `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
|| `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
|| `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap ||
|| `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
|| `[0x000000000000, 0x00007fff7fff]` || LowMem ||
MemToShadow(shadow): 0x00008fff7000 0x000091ff6dff 0x004091ff6e00 0x02008fff6fff
redzone=16
max_redzone=2048
quarantine_size_mb=256M
thread_local_quarantine_size_kb=1024K
malloc_context_size=30
SHADOW_SCALE: 3
SHADOW_GRANULARITY: 8
SHADOW_OFFSET: 0x7fff8000
==137580==Installed the sigaction for signal 11
==137580==Installed the sigaction for signal 7
==137580==Installed the sigaction for signal 8
==137580==T0: FakeStack created: 0x7f8a78dd1000 -- 0x7f8a798da000 stack_size_log: 20; mmapped 11300K, noreserve=0
==137580==T0: stack [0x7fff9b4cc000,0x7fff9bccc000) size 0x800000; local=0x7fff9bcc9684
==137580==AddressSanitizer Init done
Running main() from /home/DATA/git/Gecko/HTML/qparse/ManagedObject/googletest/googletest/src/gtest_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MPS_collect2
[ RUN ] MPS_collect2.1
MPS: MMAP PROT_NONE AT ADDRESS 0x7f8a7a844000 WITH SIZE 0x1000
MPS: ALIGNED ADDRESS TO 0x7f8a7a844000 WITH SIZE 0x1000
MPS: MMAP PROT_NONE AT ADDRESS 0x7f8a76100000 WITH SIZE 0x2000000
MPS: ALIGNED ADDRESS TO 0x7f8a76100000 WITH SIZE 0x2000000
thread stack bottom: 0x7fff9bccc000
reserved and comitted object 0x7f8a76132000 with pointer 0x615000000080
reserved and comitted object 0x7f8a76132018 with pointer 0x615000000300
second collect, p should be collected
object 0x7f8a76180000 with pointer 0x615000000080 is being freed.
Total Collection duration: 0 seconds, 2 milliseconds, 351 microseconds
deinit - destroy all roots
deinit - destroyed all roots
deinit - collect
object 0x7f8a76182000 with pointer 0x615000000300 is being freed.
Total Collection duration: 0 seconds, 1 milliseconds, 351 microseconds
deinit - collected
deinit - shutdown
MPS: MUNMAP ADDRESS 0x7f8a76100000 WITH SIZE 0x2000000
MPS: MUNMAP ADDRESS 0x7f8a7a844000 WITH SIZE 0x1000
[ OK ] MPS_collect2.1 (19 ms)
[----------] 1 test from MPS_collect2 (19 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (21 ms total)
[ PASSED ] 1 test.
debug_asan_EXECUTABLE/managed_object_tests_no_debug returned with code 0 |
a rough diff --git a/code/scan.c b/code/scan.c
index 308cffc..83c2295 100644
--- a/code/scan.c
+++ b/code/scan.c
@@ -42,6 +42,92 @@
} \
} MPS_SCAN_END(ss);
+// ASAN SUPPORT
+
+#if defined(__has_feature)
+ /* __has_feature() is supported. */
+# if __has_feature(address_sanitizer)
+# define MPS_ADDRESS_SANITIZER
+# endif
+# if __has_feature(memory_sanitizer)
+# define MPS_MEMORY_SANITIZER
+# endif
+# if __has_feature(thread_sanitizer)
+# define MPS_THREAD_SANITIZER
+# endif
+#else
+# ifdef __SANITIZE_ADDRESS__
+ /* GCC v4.8+ */
+# define MPS_ADDRESS_SANITIZER
+# endif
+# if defined(__SANITIZE_THREAD__)
+ /* GCC v7.1+ */
+# define MPS_THREAD_SANITIZER
+# endif
+#endif /* !__has_feature */
+
+/* Convenient internal macro to test version of Clang. */
+#if defined(__clang__) && defined(__clang_major__)
+# define MPS_GC_CLANG_PREREQ(major, minor) \
+ ((__clang_major__ << 8) + __clang_minor__ >= ((major) << 8) + (minor))
+# define MPS_GC_CLANG_PREREQ_FULL(major, minor, patchlevel) \
+ (MPS_GC_CLANG_PREREQ(major, (minor) + 1) \
+ || (__clang_major__ == (major) && __clang_minor__ == (minor) \
+ && __clang_patchlevel__ >= (patchlevel)))
+#else
+# define MPS_GC_CLANG_PREREQ(major, minor) 0 /* FALSE */
+# define MPS_GC_CLANG_PREREQ_FULL(major, minor, patchlevel) 0
+#endif
+
+/* Convenient internal macro to test version of gcc. */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define MPS_GC_GNUC_PREREQ(major, minor) \
+ ((__GNUC__ << 8) + __GNUC_MINOR__ >= ((major) << 8) + (minor))
+#else
+# define MPS_GC_GNUC_PREREQ(major, minor) 0 /* FALSE */
+#endif
+
+#ifndef MPS_GC_ATTR_NO_SANITIZE_ADDR
+# ifndef MPS_ADDRESS_SANITIZER
+# define MPS_GC_ATTR_NO_SANITIZE_ADDR /* empty */
+# elif MPS_GC_CLANG_PREREQ(3, 8)
+# define MPS_GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize("address")))
+# else
+# define MPS_GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize_address))
+# endif
+#endif /* !MPS_GC_ATTR_NO_SANITIZE_ADDR */
+
+#ifndef MPS_GC_ATTR_NO_SANITIZE_MEMORY
+# ifndef MPS_MEMORY_SANITIZER
+# define MPS_GC_ATTR_NO_SANITIZE_MEMORY /* empty */
+# elif MPS_GC_CLANG_PREREQ(3, 8)
+# define MPS_GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
+# else
+# define MPS_GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
+# endif
+#endif /* !MPS_GC_ATTR_NO_SANITIZE_MEMORY */
+
+#ifndef MPS_GC_ATTR_NO_SANITIZE_THREAD
+# ifndef MPS_THREAD_SANITIZER
+# define MPS_GC_ATTR_NO_SANITIZE_THREAD /* empty */
+# elif MPS_GC_CLANG_PREREQ(3, 8)
+# define MPS_GC_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
+# else
+ /* It seems that no_sanitize_thread attribute has no effect if the */
+ /* function is inlined (as of gcc 11.1.0, at least). */
+# ifndef MPS_GC_ATTR_NOINLINE
+# if MPS_GC_GNUC_PREREQ(4, 0)
+# define MPS_GC_ATTR_NOINLINE __attribute__((__noinline__))
+# elif _MSC_VER >= 1400
+# define MPS_GC_ATTR_NOINLINE __declspec(noinline)
+# else
+# define MPS_GC_ATTR_NOINLINE /* empty */
+# endif
+# endif
+# define MPS_GC_ATTR_NO_SANITIZE_THREAD \
+ MPS_GC_ATTR_NOINLINE __attribute__((no_sanitize_thread))
+# endif
+#endif /* !MPS_GC_ATTR_NO_SANITIZE_THREAD */
/* mps_scan_area -- scan contiguous area of references
*
@@ -53,6 +139,9 @@
* simple untagged references.
*/
+MPS_GC_ATTR_NO_SANITIZE_ADDR
+MPS_GC_ATTR_NO_SANITIZE_MEMORY
+MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area(mps_ss_t ss,
void *base, void *limit,
void *closure)
@@ -79,6 +168,9 @@ mps_res_t mps_scan_area(mps_ss_t ss,
* as references no matter what tag they have.
*/
+MPS_GC_ATTR_NO_SANITIZE_ADDR
+MPS_GC_ATTR_NO_SANITIZE_MEMORY
+MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_masked(mps_ss_t ss,
void *base, void *limit,
void *closure)
@@ -101,6 +193,9 @@ mps_res_t mps_scan_area_masked(mps_ss_t ss,
* only fix words whose low order bits are 0b101.
*/
+MPS_GC_ATTR_NO_SANITIZE_ADDR
+MPS_GC_ATTR_NO_SANITIZE_MEMORY
+MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_tagged(mps_ss_t ss,
void *base, void *limit,
void *closure)
@@ -130,6 +225,9 @@ mps_res_t mps_scan_area_tagged(mps_ss_t ss,
* addresses of objects around which must not be ignored.
*/
+MPS_GC_ATTR_NO_SANITIZE_ADDR
+MPS_GC_ATTR_NO_SANITIZE_MEMORY
+MPS_GC_ATTR_NO_SANITIZE_THREAD
mps_res_t mps_scan_area_tagged_or_zero(mps_ss_t ss,
void *base, void *limit,
void *closure) diff --git a/code/ss.c b/code/ss.c
index ce08810..900f2c4 100644
--- a/code/ss.c
+++ b/code/ss.c
@@ -35,7 +35,96 @@ SRCID(ss, "$Id$");
ATTRIBUTE_NOINLINE
void StackHot(void **stackOut)
{
+// ASAN SUPPORT
+
+#if defined(__has_feature)
+ /* __has_feature() is supported. */
+# if __has_feature(address_sanitizer)
+# define MPS_ADDRESS_SANITIZER
+# endif
+# if __has_feature(memory_sanitizer)
+# define MPS_MEMORY_SANITIZER
+# endif
+# if __has_feature(thread_sanitizer)
+# define MPS_THREAD_SANITIZER
+# endif
+#else
+# ifdef __SANITIZE_ADDRESS__
+ /* GCC v4.8+ */
+# define MPS_ADDRESS_SANITIZER
+# endif
+# if defined(__SANITIZE_THREAD__)
+ /* GCC v7.1+ */
+# define MPS_THREAD_SANITIZER
+# endif
+#endif /* !__has_feature */
+
+# ifdef MPS_ADDRESS_SANITIZER
+ // asan uses a fake stack, obtain the real stack
+
+ /* Define word and signed word to be unsigned and signed types of the */
+ /* size as char* or void*. */
+ /* A macro to define integer types of a pointer size. There seems to */
+ /* be no way to do this even semi-portably. The following is probably */
+ /* no better/worse than almost anything else. */
+ /* The ANSI standard suggests that size_t and ptrdiff_t might be */
+ /* better choices. But those had incorrect definitions on some older */
+ /* systems; notably "typedef int size_t" is wrong. */
+# ifdef _WIN64
+# if defined(__int64) && !defined(CPPCHECK)
+# define MPS_GC_SIGNEDWORD __int64
+# else
+# define MPS_GC_SIGNEDWORD long long
+# endif
+# else
+# define MPS_GC_SIGNEDWORD long
+# endif
+
+# define MPS_GC_UNSIGNEDWORD unsigned MPS_GC_SIGNEDWORD
+
+ typedef MPS_GC_UNSIGNEDWORD MPS_GC_word;
+
+ typedef MPS_GC_word MPS_word;
+
+ volatile MPS_word sp;
+
+# if defined(__ANDROID__) && !defined(HOST_ANDROID)
+ /* __ANDROID__ macro is defined by Android NDK gcc. */
+# define HOST_ANDROID 1
+# endif
+
+ /* First a unified test for Linux: */
+# if (defined(linux) || defined(__linux__) || defined(HOST_ANDROID)) \
+ && !defined(LINUX) && !defined(__native_client__)
+# define LINUX
+# endif
+
+# if defined(__e2k__) && defined(LINUX)
+# define E2K
+# elif defined(__s390__) && defined(LINUX)
+# define S390
+# endif
+
+# if ((defined(E2K) && defined(__clang__)) \
+ || (defined(S390) && (__clang_major__ < 8))) && !defined(CPPCHECK)
+ /* Workaround some bugs in clang: */
+ /* "undefined reference to llvm.frameaddress" error (clang-9/e2k); */
+ /* a crash in SystemZTargetLowering of libLLVM-3.8 (S390). */
+ sp = (MPS_word)&sp;
+# elif defined(CPPCHECK) || (__GNUC__ >= 4 /* MANAGED_STACK_ADDRESS_BOEHM_GC_GNUC_PREREQ(4, 0) */ \
+ && !defined(MPS_STACK_NOT_SCANNED))
+ /* TODO: Use MANAGED_STACK_ADDRESS_BOEHM_GC_GNUC_PREREQ after fixing a bug in cppcheck. */
+ sp = (MPS_word)__builtin_frame_address(0);
+# else
+ sp = (MPS_word)&sp;
+# endif
+ /* Also force stack to grow if necessary. Otherwise the */
+ /* later accesses might cause the kernel to think we're */
+ /* doing something wrong. */
+ *stackOut = (void*)sp;
+# else
*stackOut = &stackOut;
+# endif
} |
do note however, obtaining the real stack base ( |
See job003643 which was fixed. Afterwards, we had an internal discussion from 2016, and concluded the sanitizer wasn't available in the available CI systems. It is now.
The sanitizer is described in the Clang documentation at https://clang.llvm.org/docs/AddressSanitizer.html
Adding
-fsanitize=address
toCFLAGSDEBUG
in ll.gmk, then building gcbench, produces some interesting output as the MPS of course goes out of bounds and scans the stack (see below).This would make it hard for a developer using the MPS to use the sanitizer. The MPS itself might benefit from the sanitizer for defect prevention, though this is fairly unlikely.
We could fix this regression and introduce the sanitizer to the build and CI to help catch it in future.
Also, we should look for similar features in other toolchains.
The text was updated successfully, but these errors were encountered: