]> git.saurik.com Git - apple/libc.git/blame - tests/abort_tests.c
Libc-1353.60.8.tar.gz
[apple/libc.git] / tests / abort_tests.c
CommitLineData
507116e3
A
1#include <darwintest.h>
2#include <sys/types.h>
3#include <pthread.h>
4#include <mach/mach_types.h>
5#include <unistd.h>
6#include <stdlib.h>
7#include <dispatch/dispatch.h>
8
e1ee4b85
A
9typedef enum { PTHREAD, WORKQUEUE } thread_type_t;
10
11typedef enum {
12 NO_CORRUPTION,
13 SIG_CORRUPTION,
14 FULL_CORRUPTION,
15} corrupt_type_t;
16
507116e3 17static void *
e1ee4b85 18body(void *ctx)
507116e3 19{
e1ee4b85
A
20 corrupt_type_t corrupt_type = (corrupt_type_t)ctx;
21 pthread_t self = pthread_self();
22
23 T_LOG("Helper thread running: %d", corrupt_type);
24
25 // The pthread_t is stored at the top of the stack and could be
26 // corrupted because of a stack overflow. To make the test more
27 // reliable, we will manually smash the pthread struct directly.
28 switch (corrupt_type) {
29 case NO_CORRUPTION:
30 break;
31 case SIG_CORRUPTION:
32 memset(self, 0x41, 128);
33 break;
34 case FULL_CORRUPTION: /* includes TSD */
507116e3 35 memset(self, 0x41, 4096);
e1ee4b85 36 break;
507116e3 37 }
e1ee4b85 38
507116e3
A
39 // Expected behavior is that if a thread calls abort, the process should
40 // abort promptly.
41 abort();
42 T_FAIL("Abort didn't?");
43}
44
507116e3 45static void
e1ee4b85 46abort_test(thread_type_t type, corrupt_type_t corrupt_type)
507116e3
A
47{
48 pid_t child = fork();
507116e3
A
49
50 if (child == 0) {
51 T_LOG("Child running");
52 switch (type) {
53 case PTHREAD: {
54 pthread_t tid;
55 T_QUIET;
56 T_ASSERT_POSIX_ZERO(
e1ee4b85 57 pthread_create(&tid, NULL, body, (void *)corrupt_type), NULL);
507116e3
A
58 break;
59 }
60 case WORKQUEUE: {
61 dispatch_async_f(dispatch_get_global_queue(
62 DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
e1ee4b85 63 (void *)corrupt_type, &body);
507116e3
A
64 break;
65 }
66 }
67 sleep(5);
68 T_FAIL("Child didn't abort");
69 exit(-1);
e1ee4b85
A
70 }
71
72 // Wait and check the exit status of the child
73 int status = 0;
74 pid_t pid = wait(&status);
75 T_QUIET;
76 T_ASSERT_EQ(pid, child, NULL);
77 T_QUIET;
78 T_EXPECT_FALSE(WIFEXITED(status), "WIFEXITED Status: %x", status);
79 T_QUIET;
80 T_EXPECT_TRUE(WIFSIGNALED(status), "WIFSIGNALED Status: %x", status);
81 T_QUIET;
82 T_EXPECT_FALSE(WIFSTOPPED(status), "WIFSTOPPED Status: %x", status);
83
84 // This test is successful if we trigger a SIGSEGV|SIGBUS or SIGABRT
85 // since both will promptly terminate the program
86 int signal = WTERMSIG(status);
87
88#if defined(__i386__) || defined(__x86_64__)
89 // on intel pthread_self() reads a TSD so FULL corruption results
90 // in SIGSEGV/SIGBUS
91 if (corrupt_type == FULL_CORRUPTION) {
92 // any of these signals may happen depending on which libpthread
93 // you're running on.
507116e3 94 if (signal == SIGBUS) {
507116e3
A
95 T_LOG("Converting %d to SIGSEGV", signal);
96 signal = SIGSEGV;
97 }
e1ee4b85
A
98 T_EXPECT_EQ(signal, SIGSEGV, NULL);
99 T_END;
507116e3 100 }
e1ee4b85
A
101#endif
102
103 /* pthread calls abort_with_reason if only the signature is corrupt */
104 T_EXPECT_EQ(signal, SIGABRT, NULL);
507116e3
A
105}
106
107static void
108signal_handler(int signo)
109{
110 // The user's signal handler should not be called during abort
111 T_FAIL("Unexpected signal: %d\n", signo);
112}
113
e1ee4b85 114T_DECL(abort_pthread_corrupt_test_full, "Tests abort")
507116e3 115{
e1ee4b85 116 abort_test(PTHREAD, FULL_CORRUPTION);
507116e3
A
117}
118
e1ee4b85 119T_DECL(abort_workqueue_corrupt_test_full, "Tests abort")
507116e3 120{
e1ee4b85 121 abort_test(WORKQUEUE, FULL_CORRUPTION);
507116e3
A
122}
123
e1ee4b85 124T_DECL(abort_pthread_handler_test_full, "Tests abort")
507116e3
A
125{
126 // rdar://52892057
127 T_SKIP("Abort hangs if the user registers their own SIGSEGV handler");
128 signal(SIGSEGV, signal_handler);
e1ee4b85 129 abort_test(PTHREAD, FULL_CORRUPTION);
507116e3
A
130}
131
e1ee4b85 132T_DECL(abort_workqueue_handler_test_full, "Tests abort")
507116e3
A
133{
134 // rdar://52892057
135 T_SKIP("Abort hangs if the user registers their own SIGSEGV handler");
136 signal(SIGSEGV, signal_handler);
e1ee4b85
A
137 abort_test(WORKQUEUE, FULL_CORRUPTION);
138}
139
140T_DECL(abort_pthread_corrupt_test_sig, "Tests abort")
141{
142 abort_test(PTHREAD, SIG_CORRUPTION);
143}
144
145T_DECL(abort_workqueue_corrupt_test_sig, "Tests abort")
146{
147 abort_test(WORKQUEUE, SIG_CORRUPTION);
507116e3
A
148}
149
150T_DECL(abort_pthread_test, "Tests abort")
151{
e1ee4b85 152 abort_test(PTHREAD, NO_CORRUPTION);
507116e3
A
153}
154
155T_DECL(abort_workqueue_test, "Tests abort")
156{
e1ee4b85 157 abort_test(WORKQUEUE, NO_CORRUPTION);
507116e3 158}