1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <unistd.h>
21#include <sys/types.h>
22#include <fcntl.h>
23#include <setjmp.h>
24#include <signal.h>
25
26
27int err;
28
29static void __check(const char *filename, int line, int x, int expect)
30{
31 if (x != expect) {
32 printf("ERROR %s:%d - %d != %d\n",
33 filename, line, x, expect);
34 err++;
35 }
36}
37
38#define check(x, expect) __check(__FILE__, __LINE__, (x), (expect))
39
40static int satub(int src, int *p, int *ovf_result)
41{
42 int result;
43 int usr;
44
45
46
47
48
49
50
51
52
53 asm volatile("r2 = usr\n\t"
54 "r2 = clrbit(r2, #0)\n\t"
55 "usr = r2\n\t"
56 "{\n\t"
57 " %0 = satub(%2)\n\t"
58 " memw(%3) = %2\n\t"
59 "}\n\t"
60 "%1 = usr\n\t"
61 : "=r"(result), "=r"(usr)
62 : "r"(src), "r"(p)
63 : "r2", "usr", "memory");
64 *ovf_result = (usr & 1);
65 return result;
66}
67
68int read_usr_overflow(void)
69{
70 int result;
71 asm volatile("%0 = usr\n\t" : "=r"(result));
72 return result & 1;
73}
74
75
76jmp_buf jmp_env;
77int usr_overflow;
78
79static void sig_segv(int sig, siginfo_t *info, void *puc)
80{
81 usr_overflow = read_usr_overflow();
82 longjmp(jmp_env, 1);
83}
84
85int main()
86{
87 struct sigaction act;
88 int ovf;
89
90
91 act.sa_sigaction = sig_segv;
92 sigemptyset(&act.sa_mask);
93 act.sa_flags = SA_SIGINFO;
94 sigaction(SIGSEGV, &act, NULL);
95 if (setjmp(jmp_env) == 0) {
96 satub(300, 0, &ovf);
97 }
98
99 act.sa_handler = SIG_DFL;
100 sigemptyset(&act.sa_mask);
101 act.sa_flags = 0;
102
103 check(usr_overflow, 0);
104
105 puts(err ? "FAIL" : "PASS");
106 return err ? EXIT_FAILURE : EXIT_SUCCESS;
107}
108