Line data Source code
1 : #include "fd_fuzz.h"
2 : #include "../fd_util.h"
3 :
4 : #include <errno.h>
5 : #include <dirent.h>
6 : #include <fcntl.h>
7 : #include <stdlib.h>
8 : #include <stdio.h>
9 : #include <sys/stat.h>
10 : #include <sys/types.h>
11 : #include <unistd.h>
12 :
13 : /* fd_fuzz_stub.c is a stub fuzz harness for build targets without an
14 : actual fuzz engine. This harness mocks the libFuzzer command-line
15 : and can regression test against existing input files. It cannot,
16 : however, do any actual fuzz exploration. */
17 :
18 : static int
19 0 : i_am_a_stub( void ) {
20 0 : fputs( "FAIL: No fuzz engine.\n"
21 0 : "\n"
22 0 : "This fuzz target was compiled without a fuzz engine.\n"
23 0 : "You can still re-run individual test cases like so:\n"
24 0 : " <prog> path/to/file1 path/to/file2 ...\n"
25 0 : "\n"
26 0 : "Hint: Compile with CC=clang EXTRAS=fuzz to build with the libFuzzer engine.\n",
27 0 : stderr );
28 0 : return 1;
29 0 : }
30 :
31 : extern int
32 : LLVMFuzzerInitialize( int * argc,
33 : char *** argv );
34 :
35 : extern int
36 : LLVMFuzzerTestOneInput( uchar const * data,
37 : ulong data_sz );
38 :
39 : __attribute__((weak))
40 : ulong
41 : LLVMFuzzerMutate( uchar * data,
42 : ulong data_sz,
43 0 : ulong max_sz ) {
44 0 : (void)data; (void)data_sz; (void)max_sz;
45 0 : return 0UL;
46 0 : }
47 :
48 : static int
49 3369 : execute( int file ) {
50 3369 : struct stat st;
51 3369 : if( FD_UNLIKELY( 0!=fstat( file, &st ) ) ) {
52 0 : FD_LOG_ERR(( "fstat(%d) failed (%d-%s)", file, errno, fd_io_strerror( errno ) ));
53 0 : return errno;
54 0 : }
55 3369 : if( st.st_mode & S_IFDIR ) return EISDIR;
56 3369 : if( !( st.st_mode & S_IFREG ) ) return EBADF;
57 :
58 3369 : ulong file_sz = (ulong)st.st_size;
59 :
60 3369 : uchar * buf = malloc( file_sz );
61 3369 : if( !buf ) {
62 0 : FD_LOG_ERR(( "FAIL: Out of memory (failed to malloc %lu bytes)", file_sz ));
63 0 : }
64 :
65 3369 : ulong actual_read_sz;
66 3369 : int read_err = fd_io_read( file, buf, file_sz, file_sz, &actual_read_sz );
67 3369 : if( FD_UNLIKELY( read_err ) ) {
68 0 : FD_LOG_ERR(( "fd_io_read(%d,%lu) failed (%d-%s)", file, file_sz, errno, fd_io_strerror( errno ) ));
69 0 : return 1;
70 0 : }
71 :
72 3369 : LLVMFuzzerTestOneInput( buf, actual_read_sz );
73 3369 : free( buf );
74 3369 : return 0;
75 3369 : }
76 :
77 : int
78 : main( int argc,
79 18 : char ** argv ) {
80 : /* fd_boot is typically called by the target, so we don't call it here. */
81 :
82 18 : if( argc<=1 ) return i_am_a_stub();
83 :
84 18 : LLVMFuzzerInitialize( &argc, &argv );
85 :
86 3441 : for( int i=1; i<argc; i++ ) {
87 3423 : if( argv[i][0] == '-' ) continue;
88 :
89 3369 : int file0 = open( argv[i], O_RDONLY );
90 3369 : if( FD_UNLIKELY( file0<0 ) ) {
91 0 : FD_LOG_ERR(( "open(%s) failed (%d-%s)", argv[i], errno, fd_io_strerror( errno ) ));
92 0 : }
93 :
94 3369 : int err = execute( file0 );
95 3369 : if( err==EISDIR ) {
96 :
97 0 : DIR * dir = fdopendir( file0 );
98 0 : if( FD_UNLIKELY( !dir ) ) {
99 0 : FD_LOG_ERR(( "fdopendir(%d) failed (%d-%s)", file0, errno, fd_io_strerror( errno ) ));
100 0 : }
101 0 : for(;;) {
102 0 : errno = 0;
103 0 : struct dirent * ent = readdir( dir );
104 0 : if( !ent ) {
105 0 : if( FD_UNLIKELY( errno ) ) {
106 0 : FD_LOG_ERR(( "readdir(%d) failed (%d-%s)", file0, errno, fd_io_strerror( errno ) ));
107 0 : }
108 0 : break;
109 0 : }
110 0 : int file1 = openat( file0, ent->d_name, O_RDONLY );
111 0 : if( FD_UNLIKELY( file1<0 ) ) {
112 0 : FD_LOG_ERR(( "openat(%s/%s) failed (%d-%s)", argv[i], ent->d_name, errno, fd_io_strerror( errno ) ));
113 0 : }
114 0 : if( 0==execute( file1 ) ) {
115 0 : fprintf( stderr, "Executed %s/%s\n", argv[i], ent->d_name );
116 0 : }
117 0 : close( file1 );
118 0 : }
119 0 : closedir( dir );
120 0 : continue;
121 :
122 3369 : } else if( FD_UNLIKELY( err ) ) {
123 :
124 0 : fprintf( stderr, "Failed to execute %s", argv[i] );
125 :
126 3369 : } else {
127 :
128 3369 : fprintf( stderr, "Executed %s\n", argv[i] );
129 :
130 3369 : }
131 :
132 3369 : close( file0 );
133 3369 : }
134 :
135 18 : return 0;
136 18 : }
|