]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
tools/insn-fuzz: Support AFL's afl-clang-fast mode
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 1 Mar 2017 19:02:35 +0000 (19:02 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 20 Mar 2017 16:45:21 +0000 (16:45 +0000)
AFL has an alternative llvm-base instrumentation mode, which has much lower
overhead than the traditional afl-gcc.

One extra ability is to chose exactly where the master process gets
initialised to, before being forked for testing.  This point is chosen after
the call to LLVMFuzzerInitialize(), so the stack isn't being remapped
executable for every test.

Another extra ability is to feed multiple inputs into a single test process,
to reduce the number of fork() calls required overall.  Two caveats are that if
stdin is used for data, it must be unbuffered, and if input is passed via a
command line parameter, the underlying file must be opened and closed on each
iteration.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
tools/fuzz/README.afl
tools/fuzz/x86_instruction_emulator/afl-harness.c

index c5f749a6f87caae12809cc3b2d8786eafb016b04..4758de2490cfc763c9d3b845423b6a6866f7714c 100644 (file)
@@ -18,7 +18,15 @@ Use the x86 instruction emulator fuzzer as an example.
 2. run the following commands to build:
    $ cd tools/fuzz/x86_instruction_emulator
    $ make distclean
-   $ make CC=$AFLPATH/afl-gcc afl # produces afl-harness
+
+   If you have a new enough version of Clang/LLVM and have configured AFL's
+   llvm_mode, make use of afl-clang-fast:
+
+     $ make CC=$AFLPATH/afl-clang-fast afl # produces afl-harness
+
+   If not, use the default afl-gcc:
+
+     $ make CC=$AFLPATH/afl-gcc afl # produces afl-harness
 
 3. provide initial test case (fuzzer dependent, see afl-*.c):
    $ mkdir testcase_dir
index 63aff5904b1fcfa02e3640dab3feb06f29841406..154869336a858673651e3b2ce84e8c0a1b492e93 100644 (file)
@@ -17,6 +17,7 @@ int main(int argc, char **argv)
     size_t size;
     FILE *fp = NULL;
 
+    setbuf(stdin, NULL);
     setbuf(stdout, NULL);
 
     while ( 1 )
@@ -61,37 +62,44 @@ int main(int argc, char **argv)
     if ( LLVMFuzzerInitialize(&argc, &argv) )
         exit(-1);
 
-    if ( fp != stdin ) /* If not using stdin, open the provided file. */
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    __AFL_INIT();
+
+    while ( __AFL_LOOP(1000) )
+#endif
     {
-        fp = fopen(argv[optind], "rb");
-        if ( fp == NULL )
+        if ( fp != stdin ) /* If not using stdin, open the provided file. */
         {
-            perror("fopen");
-            exit(-1);
+            fp = fopen(argv[optind], "rb");
+            if ( fp == NULL )
+            {
+                perror("fopen");
+                exit(-1);
+            }
         }
-    }
 
-    size = fread(input, 1, INPUT_SIZE, fp);
+        size = fread(input, 1, INPUT_SIZE, fp);
 
-    if ( ferror(fp) )
-    {
-        perror("fread");
-        exit(-1);
-    }
+        if ( ferror(fp) )
+        {
+            perror("fread");
+            exit(-1);
+        }
 
-    if ( !feof(fp) )
-    {
-        printf("Input too large\n");
-        exit(-1);
-    }
+        if ( !feof(fp) )
+        {
+            printf("Input too large\n");
+            exit(-1);
+        }
 
-    if ( fp != stdin )
-    {
-        fclose(fp);
-        fp = NULL;
-    }
+        if ( fp != stdin )
+        {
+            fclose(fp);
+            fp = NULL;
+        }
 
-    LLVMFuzzerTestOneInput(input, size);
+        LLVMFuzzerTestOneInput(input, size);
+    }
 
     return 0;
 }