@@ -20,20 +20,50 @@ static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
20
20
// that "too many errors" has already been reported.
21
21
static __sanitizer::atomic_uint32_t caller_pcs_sz;
22
22
23
- __attribute__ ((noinline)) static bool report_this_error(uintptr_t caller) {
23
+ static char *append_str (const char *s, char *buf, const char *end) {
24
+ for (const char *p = s; (buf < end) && (*p != ' \0 ' ); ++p, ++buf)
25
+ *buf = *p;
26
+ return buf;
27
+ }
28
+
29
+ static char *append_hex (uintptr_t d, char *buf, const char *end) {
30
+ // Print the address by nibbles.
31
+ for (unsigned shift = sizeof (uintptr_t ) * 8 ; shift && buf < end;) {
32
+ shift -= 4 ;
33
+ unsigned nibble = (d >> shift) & 0xf ;
34
+ *(buf++) = nibble < 10 ? nibble + ' 0' : nibble - 10 + ' a' ;
35
+ }
36
+ return buf;
37
+ }
38
+
39
+ static void format_msg (const char *kind, uintptr_t caller, char *buf,
40
+ const char *end) {
41
+ buf = append_str (" ubsan: " , buf, end);
42
+ buf = append_str (kind, buf, end);
43
+ buf = append_str (" by 0x" , buf, end);
44
+ buf = append_hex (caller, buf, end);
45
+ buf = append_str (" \n " , buf, end);
46
+ if (buf == end)
47
+ --buf; // Make sure we don't cause a buffer overflow.
48
+ *buf = ' \0 ' ;
49
+ }
50
+
51
+ static void report_error (const char *kind, uintptr_t caller) {
24
52
if (caller == 0 )
25
- return false ;
53
+ return ;
26
54
while (true ) {
27
55
unsigned sz = __sanitizer::atomic_load_relaxed (&caller_pcs_sz);
28
- if (sz > kMaxCallerPcs ) return false ; // early exit
56
+ if (sz > kMaxCallerPcs )
57
+ return ; // early exit
29
58
// when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg
30
59
// succeeds in order to not print it multiple times.
31
60
if (sz > 0 && sz < kMaxCallerPcs ) {
32
61
uintptr_t p;
33
62
for (unsigned i = 0 ; i < sz; ++i) {
34
63
p = __sanitizer::atomic_load_relaxed (&caller_pcs[i]);
35
64
if (p == 0 ) break ; // Concurrent update.
36
- if (p == caller) return false ;
65
+ if (p == caller)
66
+ return ;
37
67
}
38
68
if (p == 0 ) continue ; // FIXME: yield?
39
69
}
@@ -44,34 +74,27 @@ __attribute__((noinline)) static bool report_this_error(uintptr_t caller) {
44
74
45
75
if (sz == kMaxCallerPcs ) {
46
76
message (" ubsan: too many errors\n " );
47
- return false ;
77
+ return ;
48
78
}
49
79
__sanitizer::atomic_store_relaxed (&caller_pcs[sz], caller);
50
- return true ;
51
- }
52
- }
53
80
54
- __attribute__ ((noinline)) static void decorate_msg(char *buf,
55
- uintptr_t caller) {
56
- // print the address by nibbles
57
- for (unsigned shift = sizeof (uintptr_t ) * 8 ; shift;) {
58
- shift -= 4 ;
59
- unsigned nibble = (caller >> shift) & 0xf ;
60
- *(buf++) = nibble < 10 ? nibble + ' 0' : nibble - 10 + ' a' ;
81
+ char msg_buf[128 ];
82
+ format_msg (kind, caller, msg_buf, msg_buf + sizeof (msg_buf));
83
+ message (msg_buf);
61
84
}
62
- // finish the message
63
- buf[0 ] = ' \n ' ;
64
- buf[1 ] = ' \0 ' ;
65
85
}
66
86
67
87
#if defined(__ANDROID__)
68
88
extern " C" __attribute__((weak)) void android_set_abort_message (const char *);
69
- static void abort_with_message (const char *msg) {
70
- if (&android_set_abort_message) android_set_abort_message (msg);
89
+ static void abort_with_message (const char *kind, uintptr_t caller) {
90
+ char msg_buf[128 ];
91
+ format_msg (kind, caller, msg_buf, msg_buf + sizeof (msg_buf));
92
+ if (&android_set_abort_message)
93
+ android_set_abort_message (msg_buf);
71
94
abort ();
72
95
}
73
96
#else
74
- static void abort_with_message (const char *) { abort (); }
97
+ static void abort_with_message (const char *kind, uintptr_t caller ) { abort (); }
75
98
#endif
76
99
77
100
#if SANITIZER_DEBUG
@@ -89,33 +112,21 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
89
112
90
113
#define INTERFACE extern " C" __attribute__((visibility(" default" )))
91
114
92
- // How many chars we need to reserve to print an address.
93
- constexpr unsigned kAddrBuf = SANITIZER_WORDSIZE / 4 ;
94
- #define MSG_TMPL (msg ) " ubsan: " msg " by 0x"
95
- #define MSG_TMPL_END (buf, msg ) (buf + sizeof (MSG_TMPL(msg)) - 1 )
96
- // Reserve an additional byte for '\n'.
97
- #define MSG_BUF_LEN (msg ) (sizeof (MSG_TMPL(msg)) + kAddrBuf + 1 )
98
-
99
- #define HANDLER_RECOVER (name, msg ) \
100
- INTERFACE void __ubsan_handle_##name##_minimal() { \
101
- uintptr_t caller = GET_CALLER_PC (); \
102
- if (!report_this_error (caller)) return ; \
103
- char msg_buf[MSG_BUF_LEN (msg)] = MSG_TMPL (msg); \
104
- decorate_msg (MSG_TMPL_END (msg_buf, msg), caller); \
105
- message (msg_buf); \
115
+ #define HANDLER_RECOVER (name, kind ) \
116
+ INTERFACE void __ubsan_handle_##name##_minimal() { \
117
+ report_error (kind, GET_CALLER_PC ()); \
106
118
}
107
119
108
- #define HANDLER_NORECOVER (name, msg ) \
109
- INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
110
- char msg_buf[MSG_BUF_LEN (msg)] = MSG_TMPL (msg); \
111
- decorate_msg (MSG_TMPL_END (msg_buf, msg), GET_CALLER_PC ()); \
112
- message (msg_buf); \
113
- abort_with_message (msg_buf); \
120
+ #define HANDLER_NORECOVER (name, kind ) \
121
+ INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
122
+ uintptr_t caller = GET_CALLER_PC (); \
123
+ report_error (kind, caller); \
124
+ abort_with_message (kind, caller); \
114
125
}
115
126
116
- #define HANDLER (name, msg ) \
117
- HANDLER_RECOVER (name, msg) \
118
- HANDLER_NORECOVER(name, msg )
127
+ #define HANDLER (name, kind ) \
128
+ HANDLER_RECOVER (name, kind) \
129
+ HANDLER_NORECOVER(name, kind )
119
130
120
131
HANDLER(type_mismatch, " type-mismatch" )
121
132
HANDLER(alignment_assumption, " alignment-assumption" )
0 commit comments