source: zzuf/trunk/src/zzuf.c @ 1667

Last change on this file since 1667 was 1667, checked in by Sam Hocevar, 14 years ago
  • Added -v/--verbose (unused yet).
  • Property svn:keywords set to Id
File size: 24.9 KB
Line 
1/*
2 *  zzuf - general purpose fuzzer
3 *  Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: zzuf.c 1667 2007-01-14 17:47:01Z sam $
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  main.c: main program
17 */
18
19#include "config.h"
20
21#if defined HAVE_STDINT_H
22#   include <stdint.h>
23#elif defined HAVE_INTTYPES_H
24#   include <inttypes.h>
25#endif
26#if defined(HAVE_GETOPT_H)
27#   include <getopt.h>
28#endif
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <regex.h>
33#include <string.h>
34#include <errno.h>
35#include <signal.h>
36#include <sys/wait.h>
37#include <sys/time.h>
38#include <sys/resource.h>
39
40#include "libzzuf.h"
41#include "random.h"
42#include "fd.h"
43#include "fuzz.h"
44#include "md5.h"
45#include "timer.h"
46
47static void loop_stdin(void);
48
49static void spawn_children(void);
50static void clean_children(void);
51static void read_children(void);
52
53static char const *sig2str(int);
54static char *merge_regex(char *, char *);
55static char *merge_file(char *, char *);
56static void set_environment(char const *);
57static void version(void);
58#if defined(HAVE_GETOPT_H)
59static void usage(void);
60#endif
61
62static struct child_list
63{
64    enum status
65    {
66        STATUS_FREE,
67        STATUS_RUNNING,
68        STATUS_SIGTERM,
69        STATUS_SIGKILL,
70        STATUS_EOF,
71    } status;
72
73    pid_t pid;
74    int fd[3]; /* 0 is debug, 1 is stderr, 2 is stdout */
75    int bytes, seed;
76    int64_t date;
77    struct md5 *ctx;
78} *child_list;
79static int maxforks = 1, child_count = 0, maxcrashes = 1, crashes = 0;
80
81static char **newargv;
82static char *protect = NULL, *refuse = NULL;
83static int seed = 0;
84static int endseed = 1;
85static int quiet = 0;
86static int maxbytes = -1;
87static int md5 = 0;
88static int checkexit = 0;
89static int verbose = 0;
90static int maxmem = -1;
91static int64_t maxtime = -1;
92static int64_t delay = 0;
93static int64_t lastlaunch = 0;
94
95#define ZZUF_FD_SET(fd, p_fdset, maxfd) \
96    if(fd >= 0) \
97    { \
98        FD_SET(fd, p_fdset); \
99        if(fd > maxfd) \
100            maxfd = fd; \
101    }
102
103#define ZZUF_FD_ISSET(fd, p_fdset) \
104    ((fd >= 0) && (FD_ISSET(fd, p_fdset)))
105
106int main(int argc, char *argv[])
107{
108    char *parser, *include, *exclude;
109    int i, cmdline = 0;
110
111    include = exclude = NULL;
112
113#if defined(HAVE_GETOPT_H)
114    for(;;)
115    {
116#   define OPTSTR "AB:cC:dD:E:F:iI:mM:nP:qr:R:s:ST:vxhV"
117#   ifdef HAVE_GETOPT_LONG
118#       define MOREINFO "Try `%s --help' for more information.\n"
119        int option_index = 0;
120        static struct option long_options[] =
121        {
122            /* Long option, needs arg, flag, short option */
123            { "autoinc",     0, NULL, 'A' },
124            { "max-bytes",   1, NULL, 'B' },
125            { "cmdline",     0, NULL, 'c' },
126            { "max-crashes", 1, NULL, 'C' },
127            { "debug",       0, NULL, 'd' },
128            { "delay",       1, NULL, 'D' },
129            { "exclude",     1, NULL, 'E' },
130            { "max-forks",   1, NULL, 'F' },
131            { "stdin",       0, NULL, 'i' },
132            { "include",     1, NULL, 'I' },
133            { "md5",         0, NULL, 'm' },
134            { "max-memory",  1, NULL, 'M' },
135            { "network",     0, NULL, 'n' },
136            { "protect",     1, NULL, 'P' },
137            { "quiet",       0, NULL, 'q' },
138            { "ratio",       1, NULL, 'r' },
139            { "refuse",      1, NULL, 'R' },
140            { "seed",        1, NULL, 's' },
141            { "signal",      0, NULL, 'S' },
142            { "max-time",    1, NULL, 'T' },
143            { "verbose",     0, NULL, 'v' },
144            { "check-exit",  0, NULL, 'x' },
145            { "help",        0, NULL, 'h' },
146            { "version",     0, NULL, 'V' },
147        };
148        int c = getopt_long(argc, argv, OPTSTR, long_options, &option_index);
149#   else
150#       define MOREINFO "Try `%s -h' for more information.\n"
151        int c = getopt(argc, argv, OPTSTR);
152#   endif
153        if(c == -1)
154            break;
155
156        switch(c)
157        {
158        case 'A': /* --autoinc */
159            setenv("ZZUF_AUTOINC", "1", 1);
160            break;
161        case 'B': /* --max-bytes */
162            maxbytes = atoi(optarg);
163            break;
164        case 'c': /* --cmdline */
165            cmdline = 1;
166            break;
167        case 'C': /* --max-crashes */
168            maxcrashes = atoi(optarg);
169            if(maxcrashes <= 0)
170                maxcrashes = 0;
171            break;
172        case 'd': /* --debug */
173            setenv("ZZUF_DEBUG", "1", 1);
174            break;
175        case 'D': /* --delay */
176            delay = (int64_t)(atof(optarg) * 1000000.0);
177            break;
178        case 'E': /* --exclude */
179            exclude = merge_regex(exclude, optarg);
180            if(!exclude)
181            {
182                printf("%s: invalid regex -- `%s'\n", argv[0], optarg);
183                return EXIT_FAILURE;
184            }
185            break;
186        case 'F': /* --max-forks */
187            maxforks = atoi(optarg) > 1 ? atoi(optarg) : 1;
188            break;
189        case 'i': /* --stdin */
190            setenv("ZZUF_STDIN", "1", 1);
191            break;
192        case 'I': /* --include */
193            include = merge_regex(include, optarg);
194            if(!include)
195            {
196                printf("%s: invalid regex -- `%s'\n", argv[0], optarg);
197                return EXIT_FAILURE;
198            }
199            break;
200        case 'm': /* --md5 */
201            md5 = 1;
202            break;
203        case 'M': /* --max-memory */
204            setenv("ZZUF_MEMORY", "1", 1);
205            maxmem = atoi(optarg);
206            break;
207        case 'n': /* --network */
208            setenv("ZZUF_NETWORK", "1", 1);
209            break;
210        case 'P': /* --protect */
211            protect = optarg;
212            break;
213        case 'q': /* --quiet */
214            quiet = 1;
215            break;
216        case 'r': /* --ratio */
217            setenv("ZZUF_RATIO", optarg, 1);
218            _zz_setratio(atof(optarg));
219            break;
220        case 'R': /* --refuse */
221            refuse = optarg;
222            break;
223        case 's': /* --seed */
224            parser = strchr(optarg, ':');
225            _zz_setseed(seed = atol(optarg));
226            endseed = parser ? atoi(parser + 1) : seed + 1;
227            break;
228        case 'S': /* --signal */
229            setenv("ZZUF_SIGNAL", "1", 1);
230            break;
231        case 'T': /* --max-time */
232            maxtime = (int64_t)(atof(optarg) * 1000000.0);
233            break;
234        case 'x': /* --check-exit */
235            checkexit = 1;
236            break;
237        case 'v': /* --verbose */
238            verbose = 1;
239            break;
240        case 'h': /* --help */
241            usage();
242            return 0;
243        case 'V': /* --version */
244            version();
245            return 0;
246        default:
247            printf("%s: invalid option -- %c\n", argv[0], c);
248            printf(MOREINFO, argv[0]);
249            return EXIT_FAILURE;
250        }
251    }
252#else
253#   define MOREINFO "Usage: %s message...\n"
254    int optind = 1;
255#endif
256
257    /* If asked to read from the standard input */
258    if(optind >= argc)
259    {
260        if(endseed != seed + 1)
261        {
262            printf("%s: seed ranges are incompatible with stdin fuzzing\n",
263                   argv[0]);
264            printf(MOREINFO, argv[0]);
265            return EXIT_FAILURE;
266        }
267
268        loop_stdin();
269
270        return EXIT_SUCCESS;
271    }
272
273    /* If asked to launch programs */
274    if(cmdline)
275    {
276        int dashdash = 0;
277
278        for(i = optind + 1; i < argc; i++)
279        {
280            if(dashdash)
281                include = merge_file(include, argv[i]);
282            else if(!strcmp("--", argv[i]))
283                dashdash = 1;
284            else if(argv[i][0] != '-')
285                include = merge_file(include, argv[i]);
286        }
287    }
288
289    if(include)
290        setenv("ZZUF_INCLUDE", include, 1);
291    if(exclude)
292        setenv("ZZUF_EXCLUDE", exclude, 1);
293    if(protect)
294        setenv("ZZUF_PROTECT", protect, 1);
295    if(refuse)
296        setenv("ZZUF_REFUSE", refuse, 1);
297
298    /* Allocate memory for children handling */
299    child_list = malloc(maxforks * sizeof(struct child_list));
300    for(i = 0; i < maxforks; i++)
301        child_list[i].status = STATUS_FREE;
302    child_count = 0;
303
304    /* Preload libzzuf.so */
305    set_environment(argv[0]);
306
307    /* Create new argv */
308    newargv = malloc((argc - optind + 1) * sizeof(char *));
309    memcpy(newargv, argv + optind, (argc - optind) * sizeof(char *));
310    newargv[argc - optind] = (char *)NULL;
311
312    /* Main loop */
313    while(child_count || seed < endseed)
314    {
315        /* Spawn new children, if necessary */
316        spawn_children();
317
318        /* Cleanup dead or dying children */
319        clean_children();
320
321        /* Read data from children */
322        read_children();
323
324        if(maxcrashes && crashes >= maxcrashes && child_count == 0)
325            break;
326    }
327
328    /* Clean up */
329    free(newargv);
330    free(child_list);
331
332    return EXIT_SUCCESS;   
333}
334
335static void loop_stdin(void)
336{
337    uint8_t md5sum[16];
338    struct md5 *ctx = NULL;
339
340    if(md5)
341        ctx = _zz_md5_init();
342
343    if(protect)
344        _zz_protect(protect);
345    if(refuse)
346        _zz_refuse(refuse);
347
348    _zz_fd_init();
349    _zz_register(0);
350
351    for(;;)
352    {
353        uint8_t buf[BUFSIZ];
354        int ret, off = 0, nw = 0;
355
356        ret = read(0, buf, BUFSIZ);
357        if(ret <= 0)
358            break;
359
360        _zz_fuzz(0, buf, ret);
361        _zz_addpos(0, ret);
362
363        if(md5)
364            _zz_md5_add(ctx, buf, ret);
365        else while(ret)
366        {
367            if((nw = write(1, buf + off, (size_t)ret)) < 0)
368                break;
369            ret -= nw;
370            off += nw;
371        }
372    }
373
374    if(md5)
375    {
376        _zz_md5_fini(md5sum, ctx);
377        fprintf(stdout, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
378                "%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
379                seed, md5sum[0], md5sum[1], md5sum[2], md5sum[3],
380                md5sum[4], md5sum[5], md5sum[6], md5sum[7],
381                md5sum[8], md5sum[9], md5sum[10], md5sum[11],
382                md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
383        fflush(stdout);
384    }
385
386    _zz_unregister(0);
387    _zz_fd_fini();
388}
389
390static char *merge_file(char *regex, char *file)
391{
392    char *newfile = malloc(5 + 2 * strlen(file) + 1 + 1), *tmp = newfile;
393
394    *tmp++ = '(';
395    *tmp++ = '^';
396    *tmp++ = '|';
397    *tmp++ = '/';
398    *tmp++ = ')';
399    while(*file)
400    {
401        if(strchr("^.[$()|*+?{\\", *file))
402            *tmp++ = '\\';
403        *tmp++ = *file++;
404    }
405    *tmp++ = '$';
406    *tmp++ = '\0';
407
408    tmp = merge_regex(regex, newfile);
409    free(newfile);
410    return tmp;
411}
412
413static char *merge_regex(char *regex, char *string)
414{
415    regex_t optre;
416
417    if(regex)
418    {
419        regex = realloc(regex, strlen(regex) + strlen(string) + 1 + 1);
420        sprintf(regex + strlen(regex) - 1, "|%s)", string);
421    }
422    else
423    {
424        regex = malloc(1 + strlen(string) + 1 + 1);
425        sprintf(regex, "(%s)", string);
426    }
427
428    if(regcomp(&optre, regex, REG_EXTENDED) != 0)
429    {
430        free(regex);
431        return NULL;
432    }
433    regfree(&optre);
434
435    return regex;
436}
437
438static void spawn_children(void)
439{
440    static int const files[] = { DEBUG_FILENO, STDERR_FILENO, STDOUT_FILENO };
441    char buf[BUFSIZ];
442    int fd[3][2];
443    int64_t now = _zz_time();
444    pid_t pid;
445    int i, j;
446
447    if(child_count == maxforks)
448        return; /* no slot */
449
450    if(seed == endseed)
451        return; /* job finished */
452
453    if(maxcrashes && crashes >= maxcrashes)
454        return; /* all jobs crashed */
455
456    if(delay > 0 && lastlaunch + delay > now)
457        return; /* too early */
458
459    /* Find the empty slot */
460    for(i = 0; i < maxforks; i++)
461        if(child_list[i].status == STATUS_FREE)
462            break;
463
464    /* Prepare communication pipe */
465    for(j = 0; j < 3; j++)
466        if(pipe(fd[j]) == -1)
467        {
468            perror("pipe");
469            return;
470        }
471
472    /* Fork and launch child */
473    pid = fork();
474    switch(pid)
475    {
476        case -1:
477            perror("fork");
478            return;
479        case 0:
480            /* We’re the child */
481            if(maxmem >= 0)
482            {
483                struct rlimit rlim;
484                rlim.rlim_cur = maxmem * 1000000;
485                rlim.rlim_max = maxmem * 1000000;
486                setrlimit(RLIMIT_AS, &rlim);
487            }
488
489            /* We loop in reverse order so that files[0] is done last,
490             * just in case one of the other dup2()ed fds had the value */
491            for(j = 3; j--; )
492            {
493                close(fd[j][0]);
494                if(fd[j][1] != files[j])
495                {
496                    dup2(fd[j][1], files[j]);
497                    close(fd[j][1]);
498                }
499            }
500
501            /* Set environment variables */
502            sprintf(buf, "%i", seed);
503            setenv("ZZUF_SEED", buf, 1);
504
505            /* Run our process */
506            if(execvp(newargv[0], newargv))
507            {
508                perror(newargv[0]);
509                exit(EXIT_FAILURE);
510            }
511            return;
512    }
513
514    /* We’re the parent, acknowledge spawn */
515    child_list[i].date = now;
516    child_list[i].pid = pid;
517    for(j = 0; j < 3; j++)
518    {
519        close(fd[j][1]);
520        child_list[i].fd[j] = fd[j][0];
521    }
522    child_list[i].bytes = 0;
523    child_list[i].seed = seed;
524    child_list[i].status = STATUS_RUNNING;
525    if(md5)
526        child_list[i].ctx = _zz_md5_init();
527
528    lastlaunch = now;
529    child_count++;
530    seed++;
531}
532
533static void clean_children(void)
534{
535    int64_t now = _zz_time();
536    int i, j;
537
538    /* Terminate children if necessary */
539    for(i = 0; i < maxforks; i++)
540    {
541        if(child_list[i].status == STATUS_RUNNING
542            && maxbytes >= 0 && child_list[i].bytes > maxbytes)
543        {
544            fprintf(stdout, "zzuf[seed=%i]: data output exceeded, sending SIGTERM\n",
545                    child_list[i].seed);
546            kill(child_list[i].pid, SIGTERM);
547            child_list[i].date = now;
548            child_list[i].status = STATUS_SIGTERM;
549        }
550
551        if(child_list[i].status == STATUS_RUNNING
552            && maxtime >= 0
553            && now > child_list[i].date + maxtime)
554        {
555            fprintf(stdout, "zzuf[seed=%i]: running time exceeded, sending SIGTERM\n",
556                    child_list[i].seed);
557            kill(child_list[i].pid, SIGTERM);
558            child_list[i].date = now;
559            child_list[i].status = STATUS_SIGTERM;
560        }
561    }
562
563    /* Kill children if necessary (still there after 2 seconds) */
564    for(i = 0; i < maxforks; i++)
565    {
566        if(child_list[i].status == STATUS_SIGTERM
567            && now > child_list[i].date + 2000000)
568        {
569            fprintf(stdout, "zzuf[seed=%i]: not responding, sending SIGKILL\n",
570                    child_list[i].seed);
571            kill(child_list[i].pid, SIGKILL);
572            child_list[i].status = STATUS_SIGKILL;
573        }
574    }
575
576    /* Collect dead children */
577    for(i = 0; i < maxforks; i++)
578    {
579        uint8_t md5sum[16];
580        int status;
581        pid_t pid;
582
583        if(child_list[i].status != STATUS_SIGKILL
584            && child_list[i].status != STATUS_SIGTERM
585            && child_list[i].status != STATUS_EOF)
586            continue;
587
588        pid = waitpid(child_list[i].pid, &status, WNOHANG);
589        if(pid <= 0)
590            continue;
591
592        if(checkexit && WIFEXITED(status) && WEXITSTATUS(status))
593        {
594            fprintf(stdout, "zzuf[seed=%i]: exit %i\n",
595                    child_list[i].seed, WEXITSTATUS(status));
596            crashes++;
597        }
598        else if(WIFSIGNALED(status)
599                 && !(WTERMSIG(status) == SIGTERM
600                       && child_list[i].status == STATUS_SIGTERM))
601        {
602            fprintf(stdout, "zzuf[seed=%i]: signal %i%s%s\n",
603                    child_list[i].seed, WTERMSIG(status),
604                    sig2str(WTERMSIG(status)),
605                      (WTERMSIG(status) == SIGKILL && maxmem >= 0) ?
606                      " (memory exceeded?)" : "");
607            crashes++;
608        }
609
610        for(j = 0; j < 3; j++)
611            if(child_list[i].fd[j] >= 0)
612                close(child_list[i].fd[j]);
613
614        if(md5)
615        {
616            _zz_md5_fini(md5sum, child_list[i].ctx);
617            fprintf(stdout, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
618                    "%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
619                    child_list[i].seed, md5sum[0], md5sum[1], md5sum[2],
620                    md5sum[3], md5sum[4], md5sum[5], md5sum[6], md5sum[7],
621                    md5sum[8], md5sum[9], md5sum[10], md5sum[11], md5sum[12],
622                    md5sum[13], md5sum[14], md5sum[15]);
623        }
624        child_list[i].status = STATUS_FREE;
625        child_count--;
626    }
627
628    fflush(stdout);
629}
630
631static void read_children(void)
632{
633    struct timeval tv;
634    fd_set fdset;
635    int i, j, ret, maxfd = 0;
636
637    /* Read data from all sockets */
638    FD_ZERO(&fdset);
639    for(i = 0; i < maxforks; i++)
640    {
641        if(child_list[i].status != STATUS_RUNNING)
642            continue;
643
644        for(j = 0; j < 3; j++)
645            ZZUF_FD_SET(child_list[i].fd[j], &fdset, maxfd);
646    }
647    tv.tv_sec = 0;
648    tv.tv_usec = 1000;
649
650    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
651    if(ret < 0)
652        perror("select");
653    if(ret <= 0)
654        return;
655
656    /* XXX: cute (i, j) iterating hack */
657    for(i = 0, j = 0; i < maxforks; i += (j == 2), j = (j + 1) % 3)
658    {
659        uint8_t buf[BUFSIZ];
660
661        if(child_list[i].status != STATUS_RUNNING)
662            continue;
663
664        if(!ZZUF_FD_ISSET(child_list[i].fd[j], &fdset))
665            continue;
666
667        ret = read(child_list[i].fd[j], buf, BUFSIZ - 1);
668        if(ret > 0)
669        {
670            /* We got data */
671            if(j != 0)
672                child_list[i].bytes += ret;
673
674            if(md5 && j == 2)
675                _zz_md5_add(child_list[i].ctx, buf, ret);
676            else if(!quiet || j == 0)
677                write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
678        }
679        else if(ret == 0)
680        {
681            /* End of file reached */
682            close(child_list[i].fd[j]);
683            child_list[i].fd[j] = -1;
684
685            if(child_list[i].fd[0] == -1 && child_list[i].fd[1] == -1
686               && child_list[i].fd[2] == -1)
687                child_list[i].status = STATUS_EOF;
688        }
689    }
690}
691
692static char const *sig2str(int signum)
693{
694    switch(signum)
695    {
696        case SIGABRT:  return " (SIGABRT)";
697        case SIGFPE:   return " (SIGFPE)";
698        case SIGILL:   return " (SIGILL)";
699        case SIGQUIT:  return " (SIGQUIT)";
700        case SIGSEGV:  return " (SIGSEGV)";
701        case SIGTRAP:  return " (SIGTRAP)";
702#ifdef SIGSYS
703        case SIGSYS:   return " (SIGSYS)";
704#endif
705#ifdef SIGEMT
706        case SIGEMT:   return " (SIGEMT)";
707#endif
708#ifdef SIGBUS
709        case SIGBUS:   return " (SIGBUS)";
710#endif
711#ifdef SIGXCPU
712        case SIGXCPU:  return " (SIGXCPU)";
713#endif
714#ifdef SIGXFSZ
715        case SIGXFSZ:  return " (SIGXFSZ)";
716#endif
717    }
718
719    return "";
720}
721
722static void set_environment(char const *progpath)
723{
724    char *libpath, *tmp;
725    int ret, len = strlen(progpath);
726#if defined __APPLE__
727#   define FILENAME "libzzuf.dylib"
728#   define EXTRAINFO ""
729#   define PRELOAD "DYLD_INSERT_LIBRARIES"
730    setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1);
731#elif defined __osf__
732#   define FILENAME "libzzuf.so"
733#   define EXTRAINFO ":DEFAULT"
734#   define PRELOAD "_RLD_LIST"
735#else
736#   define FILENAME "libzzuf.so"
737#   define EXTRAINFO ""
738#   define PRELOAD "LD_PRELOAD"
739#endif
740
741    libpath = malloc(len + strlen("/.libs/" FILENAME EXTRAINFO) + 1);
742    strcpy(libpath, progpath);
743
744    tmp = strrchr(libpath, '/');
745    strcpy(tmp ? tmp + 1 : libpath, ".libs/" FILENAME);
746    ret = access(libpath, R_OK);
747
748    strcpy(tmp ? tmp + 1 : libpath, ".libs/" FILENAME EXTRAINFO);
749    if(ret == 0)
750        setenv(PRELOAD, libpath, 1);
751    else
752        setenv(PRELOAD, LIBDIR "/" FILENAME EXTRAINFO, 1);
753    free(libpath);
754}
755
756static void version(void)
757{
758    printf("zzuf %s\n", VERSION);
759    printf("Copyright (C) 2002, 2007 Sam Hocevar <sam@zoy.org>\n");
760    printf("This is free software.  You may redistribute copies of it under the\n");
761    printf("terms of the Do What The Fuck You Want To Public License, Version 2\n");
762    printf("<http://sam.zoy.org/wtfpl/>.\n");
763    printf("There is NO WARRANTY, to the extent permitted by law.\n");
764    printf("\n");
765    printf("Written by Sam Hocevar. Report bugs to <sam@zoy.org>.\n");
766}
767
768#if defined(HAVE_GETOPT_H)
769static void usage(void)
770{
771    printf("Usage: zzuf [-AcdimnqSvx] [-r ratio] [-s seed | -s start:stop]\n");
772    printf("                          [-D delay] [-F forks] [-C crashes] [-B bytes]\n");
773    printf("                          [-T seconds] [-M bytes] [-P protect] [-R refuse]\n");
774    printf("                          [-I include] [-E exclude] [PROGRAM [--] [ARGS]...]\n");
775#   ifdef HAVE_GETOPT_LONG
776    printf("       zzuf -h | --help\n");
777    printf("       zzuf -V | --version\n");
778#   else
779    printf("       zzuf -h\n");
780    printf("       zzuf -V\n");
781#   endif
782    printf("Run PROGRAM with optional arguments ARGS and fuzz its input.\n");
783    printf("\n");
784    printf("Mandatory arguments to long options are mandatory for short options too.\n");
785#   ifdef HAVE_GETOPT_LONG
786    printf("  -A, --autoinc            increment seed each time a new file is opened\n");
787    printf("  -B, --max-bytes <n>      kill children that output more than <n> bytes\n");
788    printf("  -c, --cmdline            only fuzz files specified in the command line\n");
789    printf("  -C, --max-crashes <n>    stop after <n> children have crashed (default 1)\n");
790    printf("  -d, --debug              print debug messages\n");
791    printf("  -D, --delay              delay between forks\n");
792    printf("  -E, --exclude <regex>    do not fuzz files matching <regex>\n");
793    printf("  -F, --max-forks <n>      number of concurrent children (default 1)\n");
794    printf("  -i, --stdin              fuzz standard input\n");
795    printf("  -I, --include <regex>    only fuzz files matching <regex>\n");
796    printf("  -m, --md5                compute the output's MD5 hash\n");
797    printf("  -M, --max-memory <n>     maximum child virtual memory size in MB\n");
798    printf("  -n, --network            fuzz network input\n");
799    printf("  -P, --protect <list>     protect bytes and characters in <list>\n");
800    printf("  -q, --quiet              do not print children's messages\n");
801    printf("  -r, --ratio <ratio>      bit fuzzing ratio (default 0.004)\n");
802    printf("  -R, --refuse <list>      refuse bytes and characters in <list>\n");
803    printf("  -s, --seed <seed>        random seed (default 0)\n");
804    printf("      --seed <start:stop>  specify a seed range\n");
805    printf("  -S, --signal             prevent children from diverting crashing signals\n");
806    printf("  -T, --max-time <n>       kill children that run for more than <n> seconds\n");
807    printf("  -v, --verbose            print information during the run\n");
808    printf("  -x, --check-exit         report processes that exit with a non-zero status\n");
809    printf("  -h, --help               display this help and exit\n");
810    printf("  -V, --version            output version information and exit\n");
811#   else
812    printf("  -A               increment seed each time a new file is opened\n");
813    printf("  -B <n>           kill children that output more than <n> bytes\n");
814    printf("  -c               only fuzz files specified in the command line\n");
815    printf("  -C <n>           stop after <n> children have crashed (default 1)\n");
816    printf("  -d               print debug messages\n");
817    printf("  -D               delay between forks\n");
818    printf("  -E <regex>       do not fuzz files matching <regex>\n");
819    printf("  -F <n>           number of concurrent forks (default 1)\n");
820    printf("  -i               fuzz standard input\n");
821    printf("  -I <regex>       only fuzz files matching <regex>\n");
822    printf("  -m               compute the output's MD5 hash\n");
823    printf("  -M               maximum child virtual memory size in MB\n");
824    printf("  -n               fuzz network input\n");
825    printf("  -P <list>        protect bytes and characters in <list>\n");
826    printf("  -q               do not print the fuzzed application's messages\n");
827    printf("  -r <ratio>       bit fuzzing ratio (default 0.004)\n");
828    printf("  -R <list>        refuse bytes and characters in <list>\n");
829    printf("  -s <seed>        random seed (default 0)\n");
830    printf("     <start:stop>  specify a seed range\n");
831    printf("  -S               prevent children from diverting crashing signals\n");
832    printf("  -T <n>           kill children that run for more than <n> seconds\n");
833    printf("  -v               print information during the run\n");
834    printf("  -x               report processes that exit with a non-zero status\n");
835    printf("  -h               display this help and exit\n");
836    printf("  -V               output version information and exit\n");
837#   endif
838    printf("\n");
839    printf("Written by Sam Hocevar. Report bugs to <sam@zoy.org>.\n");
840}
841#endif
842
Note: See TracBrowser for help on using the repository browser.