1 /* Test 9 setjmp with register variables. Author: Ceriel Jacobs */ 2 3 #include <sys/types.h> 4 #include <setjmp.h> 5 #include <signal.h> 6 7 int max_error = 4; 8 #include "common.h" 9 10 11 12 char *tmpa; 13 14 int main(int argc, char *argv []); 15 void test9a(void); 16 void test9b(void); 17 void test9c(void); 18 void test9d(void); 19 void test9e(void); 20 void test9f(void); 21 char *addr(void); 22 void garbage(void); 23 void level1(void); 24 void level2(void); 25 void dolev(void); 26 void catch(int s); 27 void hard(void); 28 29 int main(argc, argv) 30 int argc; 31 char *argv[]; 32 { 33 jmp_buf envm; 34 int i, j, m = 0xFFFF; 35 36 start(9); 37 if (argc == 2) m = atoi(argv[1]); 38 for (j = 0; j < 100; j++) { 39 if (m & 00001) test9a(); 40 if (m & 00002) test9b(); 41 if (m & 00004) test9c(); 42 if (m & 00010) test9d(); 43 if (m & 00020) test9e(); 44 if (m & 00040) test9f(); 45 } 46 if (errct) quit(); 47 i = 1; 48 if (setjmp(envm) == 0) { 49 i = 2; 50 longjmp(envm, 1); 51 } else { 52 if (i == 2) { 53 /* Correct */ 54 } else if (i == 1) { 55 printf("WARNING: The setjmp/longjmp of this machine restore register variables\n\ 56 to the value they had at the time of the Setjmp\n"); 57 } else { 58 printf("Aha, I just found one last error\n"); 59 return 1; 60 } 61 } 62 quit(); 63 return(-1); /* impossible */ 64 } 65 66 void test9a() 67 { 68 register int p; 69 70 subtest = 1; 71 p = 200; 72 garbage(); 73 if (p != 200) e(1); 74 } 75 76 void test9b() 77 { 78 register int p, q; 79 80 subtest = 2; 81 p = 200; 82 q = 300; 83 garbage(); 84 if (p != 200) e(1); 85 if (q != 300) e(2); 86 } 87 88 void test9c() 89 { 90 register int p, q, r; 91 92 subtest = 3; 93 p = 200; 94 q = 300; 95 r = 400; 96 garbage(); 97 if (p != 200) e(1); 98 if (q != 300) e(2); 99 if (r != 400) e(3); 100 } 101 102 char buf[512]; 103 104 void test9d() 105 { 106 register char *p; 107 108 subtest = 4; 109 p = &buf[100]; 110 garbage(); 111 if (p != &buf[100]) e(1); 112 } 113 114 void test9e() 115 { 116 register char *p, *q; 117 118 subtest = 5; 119 p = &buf[100]; 120 q = &buf[200]; 121 garbage(); 122 if (p != &buf[100]) e(1); 123 if (q != &buf[200]) e(2); 124 } 125 126 void test9f() 127 { 128 register char *p, *q, *r; 129 130 subtest = 6; 131 p = &buf[100]; 132 q = &buf[200]; 133 r = &buf[300]; 134 garbage(); 135 if (p != &buf[100]) e(1); 136 if (q != &buf[200]) e(2); 137 if (r != &buf[300]) e(3); 138 } 139 140 jmp_buf env; 141 142 /* return address of local variable. 143 This way we can check that the stack is not polluted. 144 */ 145 char * 146 addr() 147 { 148 char a, *ret; 149 150 ret = &a; 151 return(ret); 152 } 153 154 void garbage() 155 { 156 register int i, j, k; 157 register char *p, *q, *r; 158 char *a = NULL; 159 160 p = &buf[300]; 161 q = &buf[400]; 162 r = &buf[500]; 163 i = 10; 164 j = 20; 165 k = 30; 166 switch (setjmp(env)) { 167 case 0: 168 a = addr(); 169 #ifdef __GNUC__ 170 /* 171 * to defeat the smartness of the GNU C optimizer we pretend we 172 * use 'a'. Otherwise the optimizer will not detect the looping 173 * effectuated by setjmp/longjmp, so that it thinks it can get 174 * rid of the assignment to 'a'. 175 */ 176 srand((unsigned)&a); 177 #endif 178 longjmp(env, 1); 179 break; 180 case 1: 181 if (i != 10) e(11); 182 if (j != 20) e(12); 183 if (k != 30) e(13); 184 if (p != &buf[300]) e(14); 185 if (q != &buf[400]) e(15); 186 if (r != &buf[500]) e(16); 187 tmpa = addr(); 188 if (a != tmpa) e(17); 189 level1(); 190 break; 191 case 2: 192 if (i != 10) e(21); 193 if (j != 20) e(22); 194 if (k != 30) e(23); 195 if (p != &buf[300]) e(24); 196 if (q != &buf[400]) e(25); 197 if (r != &buf[500]) e(26); 198 tmpa = addr(); 199 if (a != tmpa) e(27); 200 level2(); 201 break; 202 case 3: 203 if (i != 10) e(31); 204 if (j != 20) e(32); 205 if (k != 30) e(33); 206 if (p != &buf[300]) e(34); 207 if (q != &buf[400]) e(35); 208 if (r != &buf[500]) e(36); 209 tmpa = addr(); 210 if (a != tmpa) e(37); 211 hard(); 212 case 4: 213 if (i != 10) e(41); 214 if (j != 20) e(42); 215 if (k != 30) e(43); 216 if (p != &buf[300]) e(44); 217 if (q != &buf[400]) e(45); 218 if (r != &buf[500]) e(46); 219 tmpa = addr(); 220 if (a != tmpa) e(47); 221 return; 222 break; 223 default: e(100); 224 } 225 e(200); 226 } 227 228 void level1() 229 { 230 register char *p; 231 register int i; 232 233 i = 1000; 234 p = &buf[10]; 235 i = 200; 236 p = &buf[20]; 237 238 #ifdef __GNUC__ 239 /* 240 * to defeat the smartness of the GNU C optimizer we pretend we 241 * use 'a'. Otherwise the optimizer will not detect the looping 242 * effectuated by setjmp/longjmp, so that it thinks it can get 243 * rid of the assignment to 'a'. 244 */ 245 srand(i); 246 srand((int)*p); 247 #endif 248 249 longjmp(env, 2); 250 } 251 252 void level2() 253 { 254 register char *p; 255 register int i; 256 257 i = 0200; 258 p = &buf[2]; 259 *p = i; 260 dolev(); 261 } 262 263 void dolev() 264 { 265 register char *p; 266 register int i; 267 268 i = 010; 269 p = &buf[3]; 270 *p = i; 271 longjmp(env, 3); 272 } 273 274 void catch(s) 275 int s; 276 { 277 longjmp(env, 4); 278 } 279 280 void hard() 281 { 282 register char *p; 283 284 signal(SIGHUP, catch); 285 for (p = buf; p <= &buf[511]; p++) *p = 025; 286 kill(getpid(), SIGHUP); 287 } 288