1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dexfuzz;
18 
19 import dexfuzz.fuzzers.Fuzzer;
20 import dexfuzz.fuzzers.FuzzerMultipleExecute;
21 import dexfuzz.fuzzers.FuzzerMultipleNoExecute;
22 import dexfuzz.fuzzers.FuzzerSingleExecute;
23 import dexfuzz.fuzzers.FuzzerSingleNoExecute;
24 import dexfuzz.listeners.BisectionSearchListener;
25 import dexfuzz.listeners.ConsoleLoggerListener;
26 import dexfuzz.listeners.FinalStatusListener;
27 import dexfuzz.listeners.LogFileListener;
28 import dexfuzz.listeners.MultiplexerListener;
29 import dexfuzz.listeners.UniqueProgramTrackerListener;
30 import dexfuzz.listeners.UpdatingConsoleListener;
31 
32 /**
33  * Entrypoint class for dexfuzz.
34  */
35 public class DexFuzz {
36   // Last version update 1.9: fixed a bug in InvokeChanger.
37   private static int majorVersion = 1;
38   private static int minorVersion = 9;
39   private static int seedChangeVersion = 0;
40 
41   /**
42    * Entrypoint to dexfuzz.
43    */
main(String[] args)44   public static void main(String[] args) {
45     // Report the version number, which should be incremented every time something will cause
46     // the same input seed to produce a different result than before.
47     Log.always(String.format("DexFuzz v%d.%d.%d",
48         majorVersion, minorVersion, seedChangeVersion));
49     Log.always("");
50 
51     if (!Options.readOptions(args)) {
52       Log.error("Failed to validate options.");
53       Options.usage();
54     }
55 
56 
57     // Create a Listener that is responsible for multiple Listeners.
58     MultiplexerListener multipleListener = new MultiplexerListener();
59     multipleListener.setup();
60 
61     FinalStatusListener statusListener = new FinalStatusListener();
62     multipleListener.addListener(statusListener);
63 
64     if (Options.repeat > 1 && Options.execute) {
65       // If executing repeatedly, take care of reporting progress to the user.
66       if (Options.quiet) {
67         // Nothing if quiet is requested.
68       } else if (!Log.likelyToLog()) {
69         // Add the live updating listener if we're not printing out lots of logs.
70         multipleListener.addListener(new UpdatingConsoleListener());
71       } else {
72         // If we are dumping out lots of logs, then use the console logger instead.
73         multipleListener.addListener(new ConsoleLoggerListener());
74       }
75       // Add the file logging listener.
76       multipleListener.addListener(new LogFileListener(Options.reportLogFile));
77       if (Options.runBisectionSearch) {
78         // Add the bisection search listener.
79         multipleListener.addListener(new BisectionSearchListener());
80       }
81       // Add the unique program tracker.
82       multipleListener.addListener(new UniqueProgramTrackerListener(Options.uniqueDatabaseFile));
83     } else {
84       // Just use the basic listener.
85       multipleListener.addListener(new ConsoleLoggerListener());
86     }
87 
88     // Create the Fuzzer that uses a particular strategy for fuzzing.
89     Fuzzer fuzzer = null;
90     if ((Options.repeat > 1) && Options.execute) {
91       fuzzer = new FuzzerMultipleExecute(multipleListener);
92     } else if ((Options.repeat > 1) && !Options.execute) {
93       fuzzer = new FuzzerMultipleNoExecute(multipleListener);
94     } else if ((Options.repeat == 1) && Options.execute) {
95       fuzzer = new FuzzerSingleExecute(multipleListener);
96     } else if ((Options.repeat == 1) && !Options.execute) {
97       fuzzer = new FuzzerSingleNoExecute(multipleListener);
98     } else {
99       Log.errorAndQuit("Invalid options provided, desired fuzzer unknown.");
100     }
101     // TODO: Implement FuzzerFindMinimalMutations.
102     // TODO: Implement FuzzerGenerational.
103 
104     // Actually run the Fuzzer.
105     fuzzer.run();
106     fuzzer.printTimingInfo();
107     fuzzer.shutdown();
108 
109     // Cleanup the Listener.
110     multipleListener.shutdown();
111 
112     if (!statusListener.isSuccessful()) {
113       System.exit(1);
114     }
115   }
116 }
117