blob: 09ee756c7517fc0e8b0f550df753bd0e263a16d4 [file] [log] [blame]
/*
* 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<Executor> timedOut, List<Executor> 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<String, List<Executor>> outputMap) {
write("DIVERGENCE between some executors!");
int outputCount = 1;
for (List<Executor> 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<String, List<Executor>> 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<Mutation> mutations) {
write("Mutations Report");
for (Mutation mutation : mutations) {
write(MutationSerializer.getMutationString(mutation));
}
}
}