1 | //===-- Unittests for sigsetjmp and siglongjmp ----------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/setjmp/siglongjmp.h" |
10 | #include "src/setjmp/sigsetjmp.h" |
11 | #include "src/signal/sigprocmask.h" |
12 | #include "src/string/memcmp.h" |
13 | #include "src/string/memset.h" |
14 | #include "test/UnitTest/Test.h" |
15 | |
16 | constexpr int MAX_LOOP = 123; |
17 | int longjmp_called = 0; |
18 | |
19 | void jump_back(jmp_buf buf, int n) { |
20 | longjmp_called++; |
21 | LIBC_NAMESPACE::siglongjmp(buf, n); // Will return |n| out of setjmp |
22 | } |
23 | |
24 | TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackSaveSigs) { |
25 | jmp_buf buf; |
26 | longjmp_called = 0; |
27 | volatile int n = 0; |
28 | sigset_t old; |
29 | sigset_t mask_all; |
30 | sigset_t recovered; |
31 | LIBC_NAMESPACE::memset(&mask_all, 0xFF, sizeof(mask_all)); |
32 | LIBC_NAMESPACE::memset(&old, 0, sizeof(old)); |
33 | LIBC_NAMESPACE::memset(&recovered, 0, sizeof(recovered)); |
34 | LIBC_NAMESPACE::sigprocmask(0, nullptr, &old); |
35 | if (LIBC_NAMESPACE::sigsetjmp(buf, 1) <= MAX_LOOP) { |
36 | LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered); |
37 | ASSERT_EQ(0, LIBC_NAMESPACE::memcmp(&old, &recovered, sizeof(old))); |
38 | n = n + 1; |
39 | LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &mask_all, nullptr); |
40 | jump_back(buf, n); |
41 | } |
42 | ASSERT_EQ(longjmp_called, n); |
43 | ASSERT_EQ(n, MAX_LOOP + 1); |
44 | } |
45 | |
46 | TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackValOneSaveSigs) { |
47 | jmp_buf buf; |
48 | longjmp_called = 0; |
49 | sigset_t old; |
50 | sigset_t mask_all; |
51 | sigset_t recovered; |
52 | LIBC_NAMESPACE::memset(&mask_all, 0xFF, sizeof(mask_all)); |
53 | LIBC_NAMESPACE::memset(&old, 0, sizeof(old)); |
54 | LIBC_NAMESPACE::memset(&recovered, 0, sizeof(recovered)); |
55 | LIBC_NAMESPACE::sigprocmask(0, nullptr, &old); |
56 | int val = LIBC_NAMESPACE::sigsetjmp(buf, 1); |
57 | if (val == 0) { |
58 | LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &mask_all, nullptr); |
59 | jump_back(buf, val); |
60 | } |
61 | LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered); |
62 | ASSERT_EQ(0, LIBC_NAMESPACE::memcmp(&old, &recovered, sizeof(old))); |
63 | ASSERT_EQ(longjmp_called, 1); |
64 | ASSERT_EQ(val, 1); |
65 | } |
66 | |
67 | TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackNoSaveSigs) { |
68 | jmp_buf buf; |
69 | longjmp_called = 0; |
70 | volatile int n = 0; |
71 | if (LIBC_NAMESPACE::sigsetjmp(buf, 0) <= MAX_LOOP) { |
72 | n = n + 1; |
73 | jump_back(buf, n); |
74 | } |
75 | ASSERT_EQ(longjmp_called, n); |
76 | ASSERT_EQ(n, MAX_LOOP + 1); |
77 | } |
78 | |
79 | TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackValOneNoSaveSigs) { |
80 | jmp_buf buf; |
81 | longjmp_called = 0; |
82 | int val = LIBC_NAMESPACE::sigsetjmp(buf, 0); |
83 | if (val == 0) { |
84 | jump_back(buf, val); |
85 | } |
86 | ASSERT_EQ(longjmp_called, 1); |
87 | ASSERT_EQ(val, 1); |
88 | } |
89 | |