xref: /llvm-project/compiler-rt/test/msan/param_tls_limit.cpp (revision 310a6f12b5b80f6b77d8551c53e0fc2a2844df07)
1d21b3d34SFangrui Song // ParamTLS has limited size. Everything that does not fit is considered fully
2d21b3d34SFangrui Song // initialized.
3d21b3d34SFangrui Song 
415805c03SVitaly Buka // RUN: %clangxx_msan -fno-sanitize-memory-param-retval -O0 %s -o %t && %run %t
515805c03SVitaly Buka // RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
615805c03SVitaly Buka // RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
7d21b3d34SFangrui Song //
8*310a6f12Szhanglimin // AArch64 and LoongArch64 fail with:
9d21b3d34SFangrui Song // void f801(S<801>): Assertion `__msan_test_shadow(&s, sizeof(s)) == -1' failed
10*310a6f12Szhanglimin // XFAIL: target={{(aarch64|loongarch64).*}}
11921009e6SIlya Leoshkevich // When passing huge structs by value, SystemZ uses pointers, therefore this
12921009e6SIlya Leoshkevich // test in its present form is unfortunately not applicable.
13921009e6SIlya Leoshkevich // ABI says: "A struct or union of any other size <snip>. Replace such an
14921009e6SIlya Leoshkevich // argument by a pointer to the object, or to a copy where necessary to enforce
15921009e6SIlya Leoshkevich // call-by-value semantics."
1602012a78SPaul Robinson // XFAIL: target=s390x{{.*}}
17d21b3d34SFangrui Song 
18d21b3d34SFangrui Song #include <sanitizer/msan_interface.h>
19d21b3d34SFangrui Song #include <assert.h>
20d21b3d34SFangrui Song 
21d21b3d34SFangrui Song // This test assumes that ParamTLS size is 800 bytes.
22d21b3d34SFangrui Song 
23d21b3d34SFangrui Song // This test passes poisoned values through function argument list.
24d21b3d34SFangrui Song // In case of overflow, argument is unpoisoned.
25d21b3d34SFangrui Song #define OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == -1)
26d21b3d34SFangrui Song // In case of no overflow, it is still poisoned.
27d21b3d34SFangrui Song #define NO_OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == 0)
28d21b3d34SFangrui Song 
29d21b3d34SFangrui Song #if defined(__x86_64__)
30a1e7e401SKazuaki Ishizaki // In x86_64, if argument is partially outside tls, it is considered completely
31d21b3d34SFangrui Song // unpoisoned
32d21b3d34SFangrui Song #define PARTIAL_OVERFLOW(x) OVERFLOW(x)
33d21b3d34SFangrui Song #else
34d21b3d34SFangrui Song // In other archs, bigger arguments are splitted in multiple IR arguments, so
35d21b3d34SFangrui Song // they are considered poisoned till tls limit. Checking last byte of such arg:
36d21b3d34SFangrui Song #define PARTIAL_OVERFLOW(x) assert(__msan_test_shadow((char *)(&(x) + 1) - 1, 1) == -1)
37d21b3d34SFangrui Song #endif
38d21b3d34SFangrui Song 
39d21b3d34SFangrui Song 
40d21b3d34SFangrui Song template<int N>
41d21b3d34SFangrui Song struct S {
42d21b3d34SFangrui Song   char x[N];
43d21b3d34SFangrui Song };
44d21b3d34SFangrui Song 
f100(S<100> s)45d21b3d34SFangrui Song void f100(S<100> s) {
46d21b3d34SFangrui Song   NO_OVERFLOW(s);
47d21b3d34SFangrui Song }
48d21b3d34SFangrui Song 
f800(S<800> s)49d21b3d34SFangrui Song void f800(S<800> s) {
50d21b3d34SFangrui Song   NO_OVERFLOW(s);
51d21b3d34SFangrui Song }
52d21b3d34SFangrui Song 
f801(S<801> s)53d21b3d34SFangrui Song void f801(S<801> s) {
54d21b3d34SFangrui Song   PARTIAL_OVERFLOW(s);
55d21b3d34SFangrui Song }
56d21b3d34SFangrui Song 
f1000(S<1000> s)57d21b3d34SFangrui Song void f1000(S<1000> s) {
58d21b3d34SFangrui Song   PARTIAL_OVERFLOW(s);
59d21b3d34SFangrui Song }
60d21b3d34SFangrui Song 
f_many(int a,double b,S<800> s,int c,double d)61d21b3d34SFangrui Song void f_many(int a, double b, S<800> s, int c, double d) {
62d21b3d34SFangrui Song   NO_OVERFLOW(a);
63d21b3d34SFangrui Song   NO_OVERFLOW(b);
64d21b3d34SFangrui Song   PARTIAL_OVERFLOW(s);
65d21b3d34SFangrui Song   OVERFLOW(c);
66d21b3d34SFangrui Song   OVERFLOW(d);
67d21b3d34SFangrui Song }
68d21b3d34SFangrui Song 
69d21b3d34SFangrui Song // -8 bytes for "int a", aligned by 8
70d21b3d34SFangrui Song // -2 to make "int c" a partial fit
f_many2(int a,S<800-8-2> s,int c,double d)71d21b3d34SFangrui Song void f_many2(int a, S<800 - 8 - 2> s, int c, double d) {
72d21b3d34SFangrui Song   NO_OVERFLOW(a);
73d21b3d34SFangrui Song   NO_OVERFLOW(s);
74d21b3d34SFangrui Song   PARTIAL_OVERFLOW(c);
75d21b3d34SFangrui Song   OVERFLOW(d);
76d21b3d34SFangrui Song }
77d21b3d34SFangrui Song 
main(void)78d21b3d34SFangrui Song int main(void) {
79d21b3d34SFangrui Song   S<100> s100;
80d21b3d34SFangrui Song   S<800> s800;
81d21b3d34SFangrui Song   S<801> s801;
82d21b3d34SFangrui Song   S<1000> s1000;
83d21b3d34SFangrui Song   f100(s100);
84d21b3d34SFangrui Song   f800(s800);
85d21b3d34SFangrui Song   f801(s801);
86d21b3d34SFangrui Song   f1000(s1000);
87d21b3d34SFangrui Song 
88d21b3d34SFangrui Song   int i;
89d21b3d34SFangrui Song   double d;
90d21b3d34SFangrui Song   f_many(i, d, s800, i, d);
91d21b3d34SFangrui Song 
92d21b3d34SFangrui Song   S<800 - 8 - 2> s788;
93d21b3d34SFangrui Song   f_many2(i, s788, i, d);
94d21b3d34SFangrui Song   return 0;
95d21b3d34SFangrui Song }
96