blob: 9d7ac2f3ee16d8c90608437fb5703d839da845ad [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 * crash01.c - Test OS robustness by creating a string of random bytes and then jump to it.
3 *
4 * New version Copyright (C) 2001 Stephane Fillod <f4cfe@free.fr>
5 *
6 * Original idea (c) 1990-1994 by GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS.
7 * from crashme version: "2.4 20-MAY-1994" <GJC@WORLD.STD.COM>
8 */
9/* TODO: trapme: forge syscall with random args, and run it!! --SF */
10
11/*
12 * COPYRIGHT (c) 1990-1994 BY *
13 * GEORGE J. CARRETTE, CONCORD, MASSACHUSETTS. *
14 * ALL RIGHTS RESERVED *
15
16Permission to use, copy, modify, distribute and sell this software
17and its documentation for any purpose and without fee is hereby
18granted, provided that the above copyright notice appear in all copies
19and that both that copyright notice and this permission notice appear
20in supporting documentation, and that the name of the author
21not be used in advertising or publicity pertaining to distribution
22of the software without specific, written prior permission.
23
24THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
25ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
26HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
27ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
28WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
29ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30SOFTWARE.
31
32*/
33
plars865695b2001-08-27 22:15:12 +000034/*
35
36A signal handler is set up so that in most cases the machine exception
37generated by the illegal instructions, bad operands, etc in the procedure
38made up of random data are caught; and another round of randomness may
39be tried. Eventually a random instruction may corrupt the program or
40the machine state in such a way that the program must halt. This is
41a test of the robustness of the hardware/software for instruction
42fault handling.
43
44Note: Running this program just a few times, using total CPU time of
45less than a few seconds SHOULD NOT GIVE YOU ANY CONFIDENCE in system
46robustness. Having it run for hours, with tens of thousands of cases
47would be a different thing. It would also make sense to run this
48stress test at the same time you run other tests, like a multi-user
49benchmark.
50
51*/
52
plars865695b2001-08-27 22:15:12 +000053#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <signal.h>
57#include <setjmp.h>
58#include <time.h>
59#include <unistd.h>
60#include <sys/types.h>
61#include <sys/wait.h>
62
63#include "test.h"
plars865695b2001-08-27 22:15:12 +000064
Wanlong Gao354ebb42012-12-07 10:10:04 +080065char *TCID = "crash01";
66int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000067
68static int x_opt = 0;
69static int v_opt = 0;
70static char *v_copt;
71static int s_opt = 0;
72static char *s_copt;
73static int b_opt = 0;
74static char *b_copt;
75static int n_opt = 0;
76static char *n_copt;
77
78int verbose_level = 2;
79
80/* Also, it may spend more time trapping and less time computing random bytes
Garrett Cooper2c282152010-12-16 00:55:50 -080081 * by using the smallest incptr (while not executing already tested bits).
plars865695b2001-08-27 22:15:12 +000082 */
83int incptr = 80;
84
85int nseed;
86int ntries = 100;
87
88/* compute block of nbytes at a time */
89const int nbytes = 2000;
90
91/* max time allowed per try, in seconds */
92#define MAX_TRY_TIME 5
93
plars865695b2001-08-27 22:15:12 +000094/* in % */
95#define BLOCK_TRIGGER 80
96
plars865695b2001-08-27 22:15:12 +000097void cleanup()
98{
plars865695b2001-08-27 22:15:12 +000099
100 tst_rmdir();
101
plars865695b2001-08-27 22:15:12 +0000102}
103
104void setup()
105{
106 /*
107 * setup a default signal hander and a
108 * temporary working directory.
109 */
110 tst_sig(FORK, DEF_HANDLER, cleanup);
111
112 tst_tmpdir();
113
114 TEST_PAUSE;
115}
116
117void help()
118{
119 printf(" -x dry run, hexdump random code instead\n");
120 printf(" -v x verbose level\n");
121 printf(" -s x random seed\n");
122 printf(" -n x ntries\n");
123 printf(" -b x inc\n");
124}
125
126/*
127 * crashme [+]<nbytes>[.inc] <srand> <ntries> [nsub] [verbose]"
128 *
129 * crashme <-b [+]<nbytes>[.inc]> <-s srand> <-n ntries> [-v verbose]"
130 * crashme +2000.80 666 100 1:10:30 2
131 * nsub -> -c ?
132 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800133option_t options[] = {
134 {"v:", &v_opt, &v_copt},
135 {"s:", &s_opt, &s_copt},
136 {"n:", &n_opt, &n_copt},
137 {"b:", &b_opt, &b_copt},
138 {"x", &x_opt, NULL},
plars865695b2001-08-27 22:15:12 +0000139
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 {NULL, NULL, NULL}
plars865695b2001-08-27 22:15:12 +0000141};
142
Wanlong Gao354ebb42012-12-07 10:10:04 +0800143int malloc_flag = 1; /* to be phased out */
plars865695b2001-08-27 22:15:12 +0000144
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145void badboy_fork();
146void badboy_loop();
147void summarize_status();
plars865695b2001-08-27 22:15:12 +0000148void record_status(unsigned int n);
149
Wanlong Gao354ebb42012-12-07 10:10:04 +0800150int main(int argc, char *argv[])
plars865695b2001-08-27 22:15:12 +0000151{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200152 const char *msg;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 int lc;
plars865695b2001-08-27 22:15:12 +0000154
Cyril Hrubiscf0d6262014-09-23 14:03:31 +0200155 if ((msg = parse_opts(argc, argv, options, help)) != NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800156 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +0000157
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 if (v_opt)
159 verbose_level = atoi(v_copt);
plars865695b2001-08-27 22:15:12 +0000160
Wanlong Gao354ebb42012-12-07 10:10:04 +0800161 if (n_opt)
162 ntries = atoi(n_copt);
plars865695b2001-08-27 22:15:12 +0000163
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 if (s_opt)
165 nseed = atoi(s_copt);
plars865695b2001-08-27 22:15:12 +0000166 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 nseed = time(NULL);
plars865695b2001-08-27 22:15:12 +0000168
Wanlong Gao354ebb42012-12-07 10:10:04 +0800169 if (b_opt) {
170 int inc;
plars865695b2001-08-27 22:15:12 +0000171
Wanlong Gao354ebb42012-12-07 10:10:04 +0800172 inc = atoi(b_copt);
173 if (inc <= nbytes / 2)
174 incptr = inc;
175 else
176 tst_brkm(TBROK, cleanup,
177 "Invalid arg for -b (max: %u): %s", nbytes / 2,
178 b_copt);
179 }
180
181 setup();
182
183 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800184 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000185
186 tst_resm(TINFO, "crashme %s%d.%d %d %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800187 (malloc_flag == 0) ? "" : "+", nbytes, incptr, nseed,
188 ntries);
plars865695b2001-08-27 22:15:12 +0000189
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 srand(nseed);
191 badboy_fork();
plars865695b2001-08-27 22:15:12 +0000192
193 /* still there? */
194 tst_resm(TPASS, "we're still here, OS seems to be robust");
195
196 nseed++;
197 }
198 summarize_status();
199 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800200 tst_exit();
plars865695b2001-08-27 22:15:12 +0000201}
202
203/* ************************* */
204int badboy_pid;
205
Wanlong Gao354ebb42012-12-07 10:10:04 +0800206void my_signal(int sig, void (*func) ());
plars865695b2001-08-27 22:15:12 +0000207
Wanlong Gao354ebb42012-12-07 10:10:04 +0800208void monitor_fcn(int sig)
plars865695b2001-08-27 22:15:12 +0000209{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800210 int status;
plars865695b2001-08-27 22:15:12 +0000211
Garrett Cooper2c282152010-12-16 00:55:50 -0800212 if (verbose_level >= 3)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800213 printf("time limit reached on pid. using kill.\n");
214
215 status = kill(badboy_pid, SIGKILL);
216 if (status < 0) {
217 if (verbose_level >= 3)
218 printf("failed to kill process\n");
219 }
plars865695b2001-08-27 22:15:12 +0000220}
221
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222void badboy_fork()
plars865695b2001-08-27 22:15:12 +0000223{
224 int status, pid;
225
Wanlong Gao354ebb42012-12-07 10:10:04 +0800226 status = fork();
227 badboy_pid = status;
228 if (status == 0) { /* badboy */
plars865695b2001-08-27 22:15:12 +0000229#ifdef DEBUG_LATE_BADBOY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800230 sleep(ntries * MAX_TRY_TIME + 10);
plars865695b2001-08-27 22:15:12 +0000231#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800232 badboy_loop();
plars865695b2001-08-27 22:15:12 +0000233#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800234 exit(0); /* good goy, he survived! */
235 } else if (status < 0)
236 perror("fork");
237 else { /* parent watching over badboy */
238
239 if (verbose_level > 3)
240 printf("badboy pid = %d\n", badboy_pid);
plars865695b2001-08-27 22:15:12 +0000241
242/* don't trust the child to return at night */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800243 my_signal(SIGALRM, monitor_fcn);
244 alarm(ntries * MAX_TRY_TIME);
plars865695b2001-08-27 22:15:12 +0000245
Wanlong Gao354ebb42012-12-07 10:10:04 +0800246 pid = wait(&status);
247 if (pid <= 0) {
248 perror("wait");
249 } else {
250 if (verbose_level > 3)
251 printf("pid %d exited with status %d\n", pid,
252 status);
253 record_status(status);
254 }
255 } /* parent */
plars865695b2001-08-27 22:15:12 +0000256 alarm(0);
257}
258
259/* *************** status recording ************************* */
260
261#define STATUS_MAX 256
262static int status_table[STATUS_MAX];
263
264void record_status(unsigned int n)
265{
266 if (n >= STATUS_MAX)
267 return;
268
269 status_table[n]++;
270}
271
272/* may not work with -c option */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800273void summarize_status()
plars865695b2001-08-27 22:15:12 +0000274{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 int i;
plars865695b2001-08-27 22:15:12 +0000276
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277 if (verbose_level < 2)
278 return;
plars865695b2001-08-27 22:15:12 +0000279
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280 printf("exit status ... number of cases\n");
281 for (i = 0; i < STATUS_MAX; i++) {
282 if (status_table[i])
283 printf("%11d ... %5d\n", i, status_table[i]);
284 }
plars865695b2001-08-27 22:15:12 +0000285}
286
plars865695b2001-08-27 22:15:12 +0000287/* ************* badboy ******************************************* */
288
289jmp_buf again_buff;
290
291typedef void (*BADBOY) ();
292
293BADBOY badboy;
subrata_modakb15aafd2008-10-20 06:30:32 +0000294char *the_data;
plars865695b2001-08-27 22:15:12 +0000295
296int offset = 0;
297int next_offset = 0;
298
Wanlong Gao354ebb42012-12-07 10:10:04 +0800299char *bad_malloc(int n);
300void my_signal(int sig, void (*func) ());
301void again_handler(int sig);
302void compute_block_badboy(int n);
303void compute_badboy();
304BADBOY castaway(char *dat);
305void try_one_crash();
306void set_up_signals();
plars865695b2001-08-27 22:15:12 +0000307
308/* badboy "entry" point */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800309void badboy_loop()
plars865695b2001-08-27 22:15:12 +0000310{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 int i;
plars865695b2001-08-27 22:15:12 +0000312
Wanlong Gao354ebb42012-12-07 10:10:04 +0800313 if (malloc_flag == 0) {
314 the_data = bad_malloc((nbytes < 0) ? -nbytes : nbytes);
315 badboy = castaway(the_data);
316 printf("Badboy at %p\n", badboy);
plars865695b2001-08-27 22:15:12 +0000317 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800318
319 for (i = 0; i < ntries; ++i) {
320 compute_badboy();
321 /* level 5 */
322
323 if (!x_opt && verbose_level >= 5) {
324 if (offset)
325 printf("try %d, offset %d\n", i, offset);
326 else if (malloc_flag == 1)
327 printf("try %d, Badboy at %p\n", i, badboy);
328 else
329 printf("try %d\n", i);
330 }
331
332 if (setjmp(again_buff) == 3) {
333 if (verbose_level >= 5)
334 printf("Barfed\n");
335 } else {
336 set_up_signals();
337 alarm(MAX_TRY_TIME);
338 try_one_crash();
339 if (!x_opt && verbose_level >= 5)
340 printf("didn't barf!\n");
341 }
plars865695b2001-08-27 22:15:12 +0000342 }
plars865695b2001-08-27 22:15:12 +0000343}
344
Wanlong Gao354ebb42012-12-07 10:10:04 +0800345char *bad_malloc(int n)
plars865695b2001-08-27 22:15:12 +0000346{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800347 char *data;
Cyril Hrubisd218f342014-09-23 13:14:56 +0200348 data = malloc(n);
plars865695b2001-08-27 22:15:12 +0000349#ifdef pyr
Wanlong Gao354ebb42012-12-07 10:10:04 +0800350 if (mprotect(((int)data / PAGSIZ) * PAGSIZ, (n / PAGSIZ + 1) * PAGSIZ,
351 PROT_READ | PROT_WRITE | PROT_EXEC))
352 perror("mprotect");
plars865695b2001-08-27 22:15:12 +0000353#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800354 return (data);
plars865695b2001-08-27 22:15:12 +0000355}
356
Wanlong Gao354ebb42012-12-07 10:10:04 +0800357void again_handler(int sig)
plars865695b2001-08-27 22:15:12 +0000358{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800359 char *ss;
plars865695b2001-08-27 22:15:12 +0000360
Wanlong Gao354ebb42012-12-07 10:10:04 +0800361 switch (sig) {
362 case SIGILL:
363 ss = " illegal instruction";
364 break;
plars865695b2001-08-27 22:15:12 +0000365#ifdef SIGTRAP
Wanlong Gao354ebb42012-12-07 10:10:04 +0800366 case SIGTRAP:
367 ss = " trace trap";
368 break;
plars865695b2001-08-27 22:15:12 +0000369#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800370 case SIGFPE:
371 ss = " arithmetic exception";
372 break;
plars865695b2001-08-27 22:15:12 +0000373#ifdef SIGBUS
Wanlong Gao354ebb42012-12-07 10:10:04 +0800374 case SIGBUS:
375 ss = " bus error";
376 break;
plars865695b2001-08-27 22:15:12 +0000377#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800378 case SIGSEGV:
379 ss = " segmentation violation";
380 break;
plars865695b2001-08-27 22:15:12 +0000381#ifdef SIGIOT
Wanlong Gao354ebb42012-12-07 10:10:04 +0800382 case SIGIOT:
383 ss = " IOT instruction";
384 break;
plars865695b2001-08-27 22:15:12 +0000385#endif
386#ifdef SIGEMT
Wanlong Gao354ebb42012-12-07 10:10:04 +0800387 case SIGEMT:
388 ss = " EMT instruction";
389 break;
plars865695b2001-08-27 22:15:12 +0000390#endif
391#ifdef SIGALRM
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 case SIGALRM:
393 ss = " alarm clock";
394 break;
plars865695b2001-08-27 22:15:12 +0000395#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800396 case SIGINT:
397 ss = " interrupt";
398 break;
399 default:
400 ss = "";
401 }
402 if (verbose_level >= 5)
403 printf("Got signal %d%s\n", sig, ss);
plars865695b2001-08-27 22:15:12 +0000404
Wanlong Gao354ebb42012-12-07 10:10:04 +0800405 longjmp(again_buff, 3);
plars865695b2001-08-27 22:15:12 +0000406}
407
Wanlong Gao354ebb42012-12-07 10:10:04 +0800408void my_signal(int sig, void (*func) ())
plars865695b2001-08-27 22:15:12 +0000409{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800410 struct sigaction act;
plars865695b2001-08-27 22:15:12 +0000411
Wanlong Gao354ebb42012-12-07 10:10:04 +0800412 act.sa_handler = func;
413 memset(&act.sa_mask, 0x00, sizeof(sigset_t));
414 act.sa_flags = SA_NOMASK | SA_RESTART;
415 sigaction(sig, &act, 0);
plars865695b2001-08-27 22:15:12 +0000416}
417
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418void set_up_signals()
plars865695b2001-08-27 22:15:12 +0000419{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800420 my_signal(SIGILL, again_handler);
plars865695b2001-08-27 22:15:12 +0000421#ifdef SIGTRAP
Wanlong Gao354ebb42012-12-07 10:10:04 +0800422 my_signal(SIGTRAP, again_handler);
plars865695b2001-08-27 22:15:12 +0000423#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800424 my_signal(SIGFPE, again_handler);
plars865695b2001-08-27 22:15:12 +0000425#ifdef SIGBUS
Wanlong Gao354ebb42012-12-07 10:10:04 +0800426 my_signal(SIGBUS, again_handler);
plars865695b2001-08-27 22:15:12 +0000427#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800428 my_signal(SIGSEGV, again_handler);
plars865695b2001-08-27 22:15:12 +0000429#ifdef SIGIOT
Wanlong Gao354ebb42012-12-07 10:10:04 +0800430 my_signal(SIGIOT, again_handler);
plars865695b2001-08-27 22:15:12 +0000431#endif
432#ifdef SIGEMT
Wanlong Gao354ebb42012-12-07 10:10:04 +0800433 my_signal(SIGEMT, again_handler);
plars865695b2001-08-27 22:15:12 +0000434#endif
435#ifdef SIGALRM
Wanlong Gao354ebb42012-12-07 10:10:04 +0800436 my_signal(SIGALRM, again_handler);
plars865695b2001-08-27 22:15:12 +0000437#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800438 my_signal(SIGINT, again_handler);
plars865695b2001-08-27 22:15:12 +0000439}
440
Wanlong Gao354ebb42012-12-07 10:10:04 +0800441void compute_block_badboy(int n)
plars865695b2001-08-27 22:15:12 +0000442{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800443 int j;
plars865695b2001-08-27 22:15:12 +0000444
Wanlong Gao354ebb42012-12-07 10:10:04 +0800445 if (malloc_flag == 1) {
446 free(the_data);
447 the_data = bad_malloc(n);
448 }
plars865695b2001-08-27 22:15:12 +0000449
Wanlong Gao354ebb42012-12-07 10:10:04 +0800450 for (j = 0; j < n; ++j) {
plars865695b2001-08-27 22:15:12 +0000451#ifdef WANT_SLOW_RAND
Wanlong Gao354ebb42012-12-07 10:10:04 +0800452 the_data[j] = 0xFF & (int)(256.0 * rand() / (RAND_MAX + 1.0));
plars865695b2001-08-27 22:15:12 +0000453#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800454 the_data[j] = (rand() >> 7) & 0xFF;
plars865695b2001-08-27 22:15:12 +0000455#endif
plars038e4bc2006-06-14 02:09:33 +0000456#ifdef __powerpc__
Wanlong Gao354ebb42012-12-07 10:10:04 +0800457 __asm__
458 __volatile__("dcbst 0,%0 ; icbi 0,%0 ; isync"::"r"
459 (&the_data[j]));
plars038e4bc2006-06-14 02:09:33 +0000460#endif
461
plars865695b2001-08-27 22:15:12 +0000462 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800463
464 /* was (nbytes < 0) */
465 if (x_opt) {
466 if (verbose_level >= 1)
467 printf("Dump of %d bytes of data\n", n);
468 for (j = 0; j < n; ++j) {
469 if ((j % 16) == 0)
470 printf("\n%04d: ", j);
471
472 printf("%02x ", the_data[j]);
473 }
474 putc('\n', stdout);
475 }
plars865695b2001-08-27 22:15:12 +0000476}
477
Wanlong Gao354ebb42012-12-07 10:10:04 +0800478BADBOY castaway(char *dat)
plars865695b2001-08-27 22:15:12 +0000479{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800480 return ((BADBOY) dat);
plars865695b2001-08-27 22:15:12 +0000481}
482
Wanlong Gao354ebb42012-12-07 10:10:04 +0800483void compute_badboy()
plars865695b2001-08-27 22:15:12 +0000484{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800485 if (incptr == 0) {
486 compute_block_badboy(nbytes);
487 badboy = castaway(the_data);
488 }
489 /* trigger block generation at xx % of the current block */
490 else if ((next_offset == 0)
491 || (next_offset > ((nbytes * BLOCK_TRIGGER) / 100))) {
492 compute_block_badboy(nbytes);
493 offset = 0;
494 next_offset = offset + incptr;
495 badboy = castaway(the_data);
496 } else {
497 offset = next_offset;
498 next_offset = offset + incptr;
499 badboy = castaway(&the_data[offset]);
500 }
plars865695b2001-08-27 22:15:12 +0000501}
502
Wanlong Gao354ebb42012-12-07 10:10:04 +0800503void try_one_crash()
plars865695b2001-08-27 22:15:12 +0000504{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800505 /* was (nbytes < 0) */
506 if (!x_opt)
507 (*badboy) ();
508 else if (nbytes == 0)
509 while (1) ;
Chris Dearmanec6edca2012-10-17 19:54:01 -0700510}