xref: /aosp_15_r20/external/llvm-libc/test/src/signal/sigaltstack_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Unittests for sigaltstack -----------------------------------------===//
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 "hdr/signal_macros.h"
10 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
11 #include "src/errno/libc_errno.h"
12 #include "src/signal/linux/signal_utils.h"
13 #include "src/signal/raise.h"
14 #include "src/signal/sigaction.h"
15 #include "src/signal/sigaltstack.h"
16 #include "test/UnitTest/ErrnoSetterMatcher.h"
17 #include "test/UnitTest/Test.h"
18 
19 #include <stdint.h>
20 #include <sys/syscall.h>
21 
22 constexpr int LOCAL_VAR_SIZE = 512;
23 constexpr int ALT_STACK_SIZE = SIGSTKSZ + LOCAL_VAR_SIZE * 2;
24 static uint8_t alt_stack[ALT_STACK_SIZE];
25 
26 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
27 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
28 
29 static bool good_stack;
handler(int)30 static void handler(int) {
31   // Allocate a large stack variable so that it does not get optimized
32   // out or mapped to a register.
33   uint8_t var[LOCAL_VAR_SIZE];
34   for (int i = 0; i < LOCAL_VAR_SIZE; ++i)
35     var[i] = i;
36   // Verify that array is completely on the alt_stack.
37   for (int i = 0; i < LOCAL_VAR_SIZE; ++i) {
38     if (!(uintptr_t(var + i) < uintptr_t(alt_stack + ALT_STACK_SIZE) &&
39           uintptr_t(alt_stack) <= uintptr_t(var + i))) {
40       good_stack = false;
41       return;
42     }
43   }
44   good_stack = true;
45 }
46 
TEST(LlvmLibcSignalTest,SigaltstackRunOnAltStack)47 TEST(LlvmLibcSignalTest, SigaltstackRunOnAltStack) {
48   struct sigaction action;
49   LIBC_NAMESPACE::libc_errno = 0;
50   ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, nullptr, &action),
51               Succeeds(0));
52   action.sa_handler = handler;
53   // Indicate that the signal should be delivered on an alternate stack.
54   action.sa_flags = SA_ONSTACK;
55   ASSERT_THAT(LIBC_NAMESPACE::sigaction(SIGUSR1, &action, nullptr),
56               Succeeds(0));
57 
58   stack_t ss;
59   ss.ss_sp = alt_stack;
60   ss.ss_size = ALT_STACK_SIZE;
61   ss.ss_flags = 0;
62   // Setup the alternate stack.
63   ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Succeeds(0));
64 
65   good_stack = false;
66   LIBC_NAMESPACE::raise(SIGUSR1);
67   EXPECT_TRUE(good_stack);
68 }
69 
70 // This tests for invalid input.
TEST(LlvmLibcSignalTest,SigaltstackInvalidStack)71 TEST(LlvmLibcSignalTest, SigaltstackInvalidStack) {
72   stack_t ss;
73   ss.ss_sp = alt_stack;
74   ss.ss_size = 0;
75   ss.ss_flags = SS_ONSTACK;
76   ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(EINVAL));
77 
78   ss.ss_flags = 0;
79   ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(ENOMEM));
80 }
81