/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dexfuzz.listeners; import dexfuzz.ExecutionResult; import dexfuzz.Log; import dexfuzz.executors.Executor; import dexfuzz.program.Mutation; import dexfuzz.program.MutationSerializer; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.Map; /** * Logs events to a file. */ public class LogFileListener extends BaseListener { private BufferedWriter writer; boolean ready = false; long successfulVerification; long failedVerification; long failedMutation; long success; long timedOut; long divergence; long selfDivergent; long architectureSplit; long iterations; private String logFile; public LogFileListener(String logFile) { this.logFile = logFile; } @Override public void setup() { try { writer = new BufferedWriter(new FileWriter(logFile)); ready = true; } catch (IOException e) { e.printStackTrace(); } } @Override public void shutdown() { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } Log.always("Full log in " + logFile); } private void write(String msg) { if (!ready) { return; } try { writer.write(msg + "\n"); } catch (IOException e) { e.printStackTrace(); } } @Override public void handleSuccessfulHostVerification() { write("Host verification: SUCCESS"); successfulVerification++; } @Override public void handleFailedHostVerification(ExecutionResult verificationResult) { write("Host verification: FAILED"); failedVerification++; } @Override public void handleFailedTargetVerification() { write("Target verification: FAILED"); failedVerification++; } @Override public void handleIterationStarted(int iteration) { write("--> FUZZ " + (iteration + 1)); Date now = new Date(System.currentTimeMillis()); write("Time started: " + now.toString()); iterations++; } @Override public void handleTimeouts(List timedOut, List didNotTimeOut) { write("Some executors timed out."); write("Timed out:"); for (Executor executor : timedOut) { write(" " + executor.getName()); } if (!didNotTimeOut.isEmpty()) { write("Did not time out:"); for (Executor executor : didNotTimeOut) { write(" " + executor.getName()); } } this.timedOut++; } @Override public void handleDivergences(Map> outputMap) { write("DIVERGENCE between some executors!"); int outputCount = 1; for (List executors : outputMap.values()) { write("Output " + outputCount + ":"); for (Executor executor : executors) { write(" " + executor.getName()); } outputCount++; } divergence++; // You are probably interested in reading about these divergences while fuzzing // is taking place, so flush the writer now. try { writer.flush(); } catch (IOException e) { e.printStackTrace(); } } @Override public void handleFuzzingFile(String inputFile) { write("Fuzzing file '" + inputFile + "'"); } @Override public void handleSeed(long seed) { write("Using " + seed + " for seed."); // Flush the seed as well, so if anything goes wrong we can see what seed lead // to the issue. try { writer.flush(); } catch (IOException e) { e.printStackTrace(); } } @Override public void handleHostVerificationSigabort(ExecutionResult verificationResult) { write("Host verification: SIGABORTED"); } @Override public void handleSuccess(Map> outputMap) { write("All executors agreed on result."); success++; } @Override public void handleDumpOutput(String outputLine, Executor executor) { write(executor.getName() + " OUTPUT:"); write(outputLine); } @Override public void handleDumpVerify(String verifyLine) { write("VERIFY: " + verifyLine); } @Override public void handleMutationStats(String statsString) { write("Mutation Stats: " + statsString); } @Override public void handleTiming(String name, float elapsedTime) { write(String.format("'%s': %.3fs", name, elapsedTime)); } @Override public void handleMutationFail() { write("Mutation process: FAILED"); failedMutation++; } @Override public void handleSummary() { write(""); write("---+++--- SUMMARY ---+++---"); write("Fuzzing attempts: " + iterations); write(" Failed verification: " + failedVerification); write(" Failed mutation: " + failedMutation); write(" Timed out: " + timedOut); write("Successful: " + success); write(" Self divergent: " + selfDivergent); write(" Architecture split: " + architectureSplit); write("Produced divergence: " + divergence); long truelyDivergent = divergence - (selfDivergent + architectureSplit); long verified = success + timedOut + truelyDivergent; write(""); float verifiedTotalRatio = (((float) (verified)) / iterations) * 100.0f; write(String.format("Percentage Verified/Total: %.3f%%", verifiedTotalRatio)); float timedOutVerifiedRatio = (((float) timedOut) / (verified)) * 100.0f; write(String.format("Percentage Timed Out/Verified: %.3f%%", timedOutVerifiedRatio)); float successfulVerifiedRatio = (((float) success) / (verified)) * 100.0f; write(String.format("Percentage Successful/Verified: %.3f%%", successfulVerifiedRatio)); float divergentVerifiedRatio = (((float) truelyDivergent) / (verified)) * 100.0f; write(String.format("Percentage Divergent/Verified: %.3f%%", divergentVerifiedRatio)); write("---+++--- SUMMARY ---+++---"); write(""); } @Override public void handleIterationFinished(int iteration) { write(""); } @Override public void handleSuccessfullyFuzzedFile(String programName) { write("Successfully fuzzed file '" + programName + "'"); } @Override public void handleSelfDivergence() { write("Golden Executor was self-divergent!"); selfDivergent++; } @Override public void handleArchitectureSplit() { write("Divergent outputs align with difference in architectures."); architectureSplit++; } @Override public void handleMessage(String msg) { write(msg); } @Override public void handleMutations(List mutations) { write("Mutations Report"); for (Mutation mutation : mutations) { write(MutationSerializer.getMutationString(mutation)); } } }