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.listeners; 18 19 import dexfuzz.ExecutionResult; 20 import dexfuzz.Log; 21 import dexfuzz.executors.Executor; 22 import dexfuzz.program.Mutation; 23 import dexfuzz.program.MutationSerializer; 24 25 import java.io.BufferedWriter; 26 import java.io.FileWriter; 27 import java.io.IOException; 28 import java.util.Date; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * Logs events to a file. 34 */ 35 public class LogFileListener extends BaseListener { 36 private BufferedWriter writer; 37 boolean ready = false; 38 39 long successfulVerification; 40 long failedVerification; 41 long failedMutation; 42 long success; 43 long timedOut; 44 long divergence; 45 long selfDivergent; 46 long architectureSplit; 47 long iterations; 48 49 private String logFile; 50 LogFileListener(String logFile)51 public LogFileListener(String logFile) { 52 this.logFile = logFile; 53 } 54 55 @Override setup()56 public void setup() { 57 try { 58 writer = new BufferedWriter(new FileWriter(logFile)); 59 ready = true; 60 } catch (IOException e) { 61 e.printStackTrace(); 62 } 63 } 64 65 @Override shutdown()66 public void shutdown() { 67 try { 68 writer.close(); 69 } catch (IOException e) { 70 e.printStackTrace(); 71 } 72 Log.always("Full log in " + logFile); 73 } 74 write(String msg)75 private void write(String msg) { 76 if (!ready) { 77 return; 78 } 79 try { 80 writer.write(msg + "\n"); 81 } catch (IOException e) { 82 e.printStackTrace(); 83 } 84 } 85 86 @Override handleSuccessfulHostVerification()87 public void handleSuccessfulHostVerification() { 88 write("Host verification: SUCCESS"); 89 successfulVerification++; 90 } 91 92 @Override handleFailedHostVerification(ExecutionResult verificationResult)93 public void handleFailedHostVerification(ExecutionResult verificationResult) { 94 write("Host verification: FAILED"); 95 failedVerification++; 96 } 97 98 @Override handleFailedTargetVerification()99 public void handleFailedTargetVerification() { 100 write("Target verification: FAILED"); 101 failedVerification++; 102 } 103 104 @Override handleIterationStarted(int iteration)105 public void handleIterationStarted(int iteration) { 106 write("--> FUZZ " + (iteration + 1)); 107 Date now = new Date(System.currentTimeMillis()); 108 write("Time started: " + now.toString()); 109 iterations++; 110 } 111 112 @Override handleTimeouts(List<Executor> timedOut, List<Executor> didNotTimeOut)113 public void handleTimeouts(List<Executor> timedOut, List<Executor> didNotTimeOut) { 114 write("Some executors timed out."); 115 write("Timed out:"); 116 for (Executor executor : timedOut) { 117 write(" " + executor.getName()); 118 } 119 if (!didNotTimeOut.isEmpty()) { 120 write("Did not time out:"); 121 for (Executor executor : didNotTimeOut) { 122 write(" " + executor.getName()); 123 } 124 } 125 this.timedOut++; 126 } 127 128 @Override handleDivergences(Map<String, List<Executor>> outputMap)129 public void handleDivergences(Map<String, List<Executor>> outputMap) { 130 write("DIVERGENCE between some executors!"); 131 int outputCount = 1; 132 for (List<Executor> executors : outputMap.values()) { 133 write("Output " + outputCount + ":"); 134 for (Executor executor : executors) { 135 write(" " + executor.getName()); 136 } 137 outputCount++; 138 } 139 divergence++; 140 141 // You are probably interested in reading about these divergences while fuzzing 142 // is taking place, so flush the writer now. 143 try { 144 writer.flush(); 145 } catch (IOException e) { 146 e.printStackTrace(); 147 } 148 } 149 150 @Override handleFuzzingFile(String inputFile)151 public void handleFuzzingFile(String inputFile) { 152 write("Fuzzing file '" + inputFile + "'"); 153 } 154 155 @Override handleSeed(long seed)156 public void handleSeed(long seed) { 157 write("Using " + seed + " for seed."); 158 // Flush the seed as well, so if anything goes wrong we can see what seed lead 159 // to the issue. 160 try { 161 writer.flush(); 162 } catch (IOException e) { 163 e.printStackTrace(); 164 } 165 } 166 167 @Override handleHostVerificationSigabort(ExecutionResult verificationResult)168 public void handleHostVerificationSigabort(ExecutionResult verificationResult) { 169 write("Host verification: SIGABORTED"); 170 } 171 172 @Override handleSuccess(Map<String, List<Executor>> outputMap)173 public void handleSuccess(Map<String, List<Executor>> outputMap) { 174 write("All executors agreed on result."); 175 success++; 176 } 177 178 @Override handleDumpOutput(String outputLine, Executor executor)179 public void handleDumpOutput(String outputLine, Executor executor) { 180 write(executor.getName() + " OUTPUT:"); 181 write(outputLine); 182 } 183 184 @Override handleDumpVerify(String verifyLine)185 public void handleDumpVerify(String verifyLine) { 186 write("VERIFY: " + verifyLine); 187 } 188 189 @Override handleMutationStats(String statsString)190 public void handleMutationStats(String statsString) { 191 write("Mutation Stats: " + statsString); 192 } 193 194 @Override handleTiming(String name, float elapsedTime)195 public void handleTiming(String name, float elapsedTime) { 196 write(String.format("'%s': %.3fs", name, elapsedTime)); 197 } 198 199 @Override handleMutationFail()200 public void handleMutationFail() { 201 write("Mutation process: FAILED"); 202 failedMutation++; 203 } 204 205 @Override handleSummary()206 public void handleSummary() { 207 write(""); 208 write("---+++--- SUMMARY ---+++---"); 209 write("Fuzzing attempts: " + iterations); 210 write(" Failed verification: " + failedVerification); 211 write(" Failed mutation: " + failedMutation); 212 write(" Timed out: " + timedOut); 213 write("Successful: " + success); 214 write(" Self divergent: " + selfDivergent); 215 write(" Architecture split: " + architectureSplit); 216 write("Produced divergence: " + divergence); 217 218 long truelyDivergent = divergence - (selfDivergent + architectureSplit); 219 long verified = success + timedOut + truelyDivergent; 220 221 write(""); 222 223 float verifiedTotalRatio = 224 (((float) (verified)) / iterations) * 100.0f; 225 write(String.format("Percentage Verified/Total: %.3f%%", verifiedTotalRatio)); 226 227 float timedOutVerifiedRatio = 228 (((float) timedOut) / (verified)) * 100.0f; 229 write(String.format("Percentage Timed Out/Verified: %.3f%%", timedOutVerifiedRatio)); 230 231 float successfulVerifiedRatio = 232 (((float) success) / (verified)) * 100.0f; 233 write(String.format("Percentage Successful/Verified: %.3f%%", successfulVerifiedRatio)); 234 235 float divergentVerifiedRatio = 236 (((float) truelyDivergent) / (verified)) * 100.0f; 237 write(String.format("Percentage Divergent/Verified: %.3f%%", divergentVerifiedRatio)); 238 239 write("---+++--- SUMMARY ---+++---"); 240 write(""); 241 } 242 243 @Override handleIterationFinished(int iteration)244 public void handleIterationFinished(int iteration) { 245 write(""); 246 } 247 248 @Override handleSuccessfullyFuzzedFile(String programName)249 public void handleSuccessfullyFuzzedFile(String programName) { 250 write("Successfully fuzzed file '" + programName + "'"); 251 } 252 253 @Override handleSelfDivergence()254 public void handleSelfDivergence() { 255 write("Golden Executor was self-divergent!"); 256 selfDivergent++; 257 } 258 259 @Override handleArchitectureSplit()260 public void handleArchitectureSplit() { 261 write("Divergent outputs align with difference in architectures."); 262 architectureSplit++; 263 } 264 265 @Override handleMessage(String msg)266 public void handleMessage(String msg) { 267 write(msg); 268 } 269 270 @Override handleMutations(List<Mutation> mutations)271 public void handleMutations(List<Mutation> mutations) { 272 write("Mutations Report"); 273 for (Mutation mutation : mutations) { 274 write(MutationSerializer.getMutationString(mutation)); 275 } 276 } 277 } 278