|
1 |
| -// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t |
2 |
| -// RUN: %run %t 2>&1 | FileCheck %s |
| 1 | +// RUN: %clangxx -DDETERMINE_UNIQUE %s -o %t-unique |
| 2 | +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -DSHARED_LIB -fPIC -shared -o %t-so.so |
| 3 | +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t %t-so.so |
| 4 | +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK $(%run %t-unique UNIQUE) |
3 | 5 | // Verify that we can disable symbolization if needed:
|
4 |
| -// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM |
| 6 | +// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM $(%run %t-unique NOSYM-UNIQUE) |
5 | 7 | // XFAIL: windows-msvc
|
6 | 8 | // Unsupported function flag
|
7 | 9 | // UNSUPPORTED: openbsd
|
8 | 10 |
|
| 11 | +#ifdef DETERMINE_UNIQUE |
| 12 | + |
| 13 | +#include <iostream> |
| 14 | + |
| 15 | +#include "../../../../../lib/sanitizer_common/sanitizer_platform.h" |
| 16 | + |
| 17 | +int main(int, char **argv) { |
| 18 | + if (!SANITIZER_NON_UNIQUE_TYPEINFO) |
| 19 | + std::cout << "--check-prefix=" << argv[1]; |
| 20 | +} |
| 21 | + |
| 22 | +#else |
| 23 | + |
| 24 | +struct Shared {}; |
| 25 | +using FnShared = void (*)(Shared *); |
| 26 | +FnShared getShared(); |
| 27 | + |
| 28 | +struct __attribute__((visibility("hidden"))) Hidden {}; |
| 29 | +using FnHidden = void (*)(Hidden *); |
| 30 | +FnHidden getHidden(); |
| 31 | + |
| 32 | +namespace { |
| 33 | +struct Private {}; |
| 34 | +} // namespace |
| 35 | +using FnPrivate = void (*)(void *); |
| 36 | +FnPrivate getPrivate(); |
| 37 | + |
| 38 | +#ifdef SHARED_LIB |
| 39 | + |
| 40 | +void fnShared(Shared *) {} |
| 41 | +FnShared getShared() { return fnShared; } |
| 42 | + |
| 43 | +void fnHidden(Hidden *) {} |
| 44 | +FnHidden getHidden() { return fnHidden; } |
| 45 | + |
| 46 | +void fnPrivate(Private *) {} |
| 47 | +FnPrivate getPrivate() { return reinterpret_cast<FnPrivate>(fnPrivate); } |
| 48 | + |
| 49 | +#else |
| 50 | + |
9 | 51 | #include <stdint.h>
|
10 | 52 |
|
11 | 53 | void f() {}
|
@@ -64,12 +106,31 @@ void check_noexcept_calls() {
|
64 | 106 | p2(0);
|
65 | 107 | }
|
66 | 108 |
|
| 109 | +void check_cross_dso() { |
| 110 | + getShared()(nullptr); |
| 111 | + |
| 112 | + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnHidden(Hidden*) through pointer to incorrect function type 'void (*)(Hidden *)' |
| 113 | + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(Hidden *)' |
| 114 | + getHidden()(nullptr); |
| 115 | + |
| 116 | + // TODO: Unlike GCC, Clang fails to prefix the typeinfo name for the function |
| 117 | + // type with "*", so this erroneously only fails for "*UNIQUE": |
| 118 | + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnPrivate((anonymous namespace)::Private*) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' |
| 119 | + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' |
| 120 | + reinterpret_cast<void (*)(Private *)>(getPrivate())(nullptr); |
| 121 | +} |
| 122 | + |
67 | 123 | int main(void) {
|
68 | 124 | make_valid_call();
|
69 | 125 | make_invalid_call();
|
70 | 126 | check_noexcept_calls();
|
| 127 | + check_cross_dso(); |
71 | 128 | // Check that no more errors will be printed.
|
72 | 129 | // CHECK-NOT: runtime error: call to function
|
73 | 130 | // NOSYM-NOT: runtime error: call to function
|
74 | 131 | make_invalid_call();
|
75 | 132 | }
|
| 133 | + |
| 134 | +#endif |
| 135 | + |
| 136 | +#endif |
0 commit comments