NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-sparc/53277 (Many ubsan tests fail on sparc)
Synopsis: Many ubsan tests fail on sparc
State-Changed-From-To: open->analyzed
State-Changed-By: riastradh%NetBSD.org@localhost
State-Changed-When: Fri, 18 Apr 2025 22:37:27 +0000
State-Changed-Why:
I tried compiling and running the t_ubsan_int_add_overflow program on
sparc under anita:
$ cat >test.c
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int help(int);
#ifndef PIC_MAIN
int help(int count) {volatile int l = INT_MAX; l+= count; return l;}
#endif
#ifndef PIC_FOO
int main(int argc, char **argv) {volatile int l = INT_MAX; l+=argc; return l;}
#endif
$ cc -fsanitize=undefined -o test test.c
$ ./test
It didn't seem to react, but ^T showed the same instruction address
repeatedly:
[ 5401.0213825] load: 0.65 cmd: test 1508 [0xed9c9454] 4.06u 46.48s 90% 2956k
[ 5403.7323765] load: 0.65 cmd: test 1508 [0xed9c9454] 4.22u 48.94s 91% 2956k
[ 5404.3214200] load: 0.65 cmd: test 1508 [0xed9c9454] 4.27u 49.45s 91% 2956k
[ 5404.4614085] load: 0.65 cmd: test 1508 [0xed9c9454] 4.30u 49.55s 91% 2956k
So I hit ^\ and it dumped core. Here's what gdb said about the core:
Core was generated by `test'.
Program terminated with signal SIGQUIT, Quit.
#0 0xed9c9454 in __sanitizer::StaticSpinMutex::LockSlow (
this=0xede968b8 <__sanitizer::report_file_mu>)
at /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_mutex.cpp:24
warning: 24 /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_mutex.cpp: No such file or directory
(gdb) bt
#0 0xed9c9454 in __sanitizer::StaticSpinMutex::LockSlow (
this=0xede968b8 <__sanitizer::report_file_mu>)
at /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_mutex.cpp:24
#1 0xed9c72dc in __sanitizer::StaticSpinMutex::Lock (
this=0xede968b8 <__sanitizer::report_file_mu>)
at /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_mutex.h:32
#2 __sanitizer::GenericScopedLock<__sanitizer::StaticSpinMutex>::GenericScopedLock (mu=0xede968b8 <__sanitizer::report_file_mu>, this=<synthetic pointer>)
at /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_mutex.h:367
this=0xed9f4260 <__sanitizer::report_file>,
buffer=0xefffedd8 "UndefinedBehaviorSanitizer: CHECK failed: sanitizer_mutex.h:42 \"((atomic_load(&state_, memory_order_relaxed))) == ((1))\" (0xff, 0x1) (tid=928)\n", length=143)
at /usr/src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_posix.cpp:271
This bespoke spin lock built out of bespoke atomic operations in terms
of __sync_* compiler builtins has an internal state of 0xff instead of
1. It turns out this sanitizer logic is simply misusing the
__sync_lock_test_and_set API to implement a C11-style atomic_exchange:
when you do __sync_lock_test_and_set(&lock, 1), it is not guaranteed to
set lock to 1; it is only guaranteed to set it to something nonzero.
On sparc, this value is 0xff, because that's what ou get from the
LDSTUB instruction.
Fortunately, I think we can just change this assertion:
void CheckLocked() const CHECK_LOCKED() {
CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1);
}
to:
void CheckLocked() const CHECK_LOCKED() {
CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0);
}
Home |
Main Index |
Thread Index |
Old Index