diff options
7 files changed, 112 insertions, 27 deletions
diff --git a/tools/dexfuzz/src/dexfuzz/DexFuzz.java b/tools/dexfuzz/src/dexfuzz/DexFuzz.java index 7337ffc2b6..18db4c1f1a 100644 --- a/tools/dexfuzz/src/dexfuzz/DexFuzz.java +++ b/tools/dexfuzz/src/dexfuzz/DexFuzz.java @@ -21,9 +21,9 @@ import dexfuzz.fuzzers.FuzzerMultipleExecute; import dexfuzz.fuzzers.FuzzerMultipleNoExecute; import dexfuzz.fuzzers.FuzzerSingleExecute; import dexfuzz.fuzzers.FuzzerSingleNoExecute; -import dexfuzz.listeners.BaseListener; import dexfuzz.listeners.BisectionSearchListener; import dexfuzz.listeners.ConsoleLoggerListener; +import dexfuzz.listeners.FinalStatusListener; import dexfuzz.listeners.LogFileListener; import dexfuzz.listeners.MultiplexerListener; import dexfuzz.listeners.UniqueProgramTrackerListener; @@ -52,12 +52,15 @@ public class DexFuzz { Options.usage(); } - // Create the Listener, which will listen for events and report them. - BaseListener listener = null; + + // Create a Listener that is responsible for multiple Listeners. + MultiplexerListener multipleListener = new MultiplexerListener(); + multipleListener.setup(); + + FinalStatusListener statusListener = new FinalStatusListener(); + multipleListener.addListener(statusListener); + if (Options.repeat > 1 && Options.execute) { - // Create a Listener that is responsible for multiple Listeners. - MultiplexerListener multipleListener = new MultiplexerListener(); - multipleListener.setup(); // Add the live updating listener, but only if we're not printing out lots of logs. if (!Log.likelyToLog()) { multipleListener.addListener(new UpdatingConsoleListener()); @@ -73,22 +76,21 @@ public class DexFuzz { } // Add the unique program tracker. multipleListener.addListener(new UniqueProgramTrackerListener(Options.uniqueDatabaseFile)); - listener = multipleListener; } else { // Just use the basic listener. - listener = new ConsoleLoggerListener(); + multipleListener.addListener(new ConsoleLoggerListener()); } // Create the Fuzzer that uses a particular strategy for fuzzing. Fuzzer fuzzer = null; if ((Options.repeat > 1) && Options.execute) { - fuzzer = new FuzzerMultipleExecute(listener); + fuzzer = new FuzzerMultipleExecute(multipleListener); } else if ((Options.repeat > 1) && !Options.execute) { - fuzzer = new FuzzerMultipleNoExecute(listener); + fuzzer = new FuzzerMultipleNoExecute(multipleListener); } else if ((Options.repeat == 1) && Options.execute) { - fuzzer = new FuzzerSingleExecute(listener); + fuzzer = new FuzzerSingleExecute(multipleListener); } else if ((Options.repeat == 1) && !Options.execute) { - fuzzer = new FuzzerSingleNoExecute(listener); + fuzzer = new FuzzerSingleNoExecute(multipleListener); } else { Log.errorAndQuit("Invalid options provided, desired fuzzer unknown."); } @@ -101,6 +103,10 @@ public class DexFuzz { fuzzer.shutdown(); // Cleanup the Listener. - listener.shutdown(); + multipleListener.shutdown(); + + if (!statusListener.isSuccessful()) { + System.exit(1); + } } } diff --git a/tools/dexfuzz/src/dexfuzz/executors/Device.java b/tools/dexfuzz/src/dexfuzz/executors/Device.java index 72f73b88f5..ba1365eee0 100644 --- a/tools/dexfuzz/src/dexfuzz/executors/Device.java +++ b/tools/dexfuzz/src/dexfuzz/executors/Device.java @@ -272,7 +272,7 @@ public class Device { } public void cleanCodeCache(Architecture architecture, String testLocation, String programName) { - String command = "rm -f " + getCacheLocation(architecture) + String command = getExecutionPrefixWithAdb("shell") + "rm -f " + getCacheLocation(architecture) + getOatFileName(testLocation, programName); executeCommand(command, false); } @@ -280,7 +280,11 @@ public class Device { public void pushProgramToDevice(String programName, String testLocation) { assert(!isHost); if (!programPushed) { - executeCommand(getExecutionPrefixWithAdb("push") + programName + " " + testLocation, false); + String command = getExecutionPrefixWithAdb("push") + programName + " " + testLocation; + ExecutionResult result = executeCommand(command, false); + if (result.returnValue != 0) { + Log.errorAndQuit("Could not ADB PUSH program to device."); + } programPushed = true; } } diff --git a/tools/dexfuzz/src/dexfuzz/listeners/FinalStatusListener.java b/tools/dexfuzz/src/dexfuzz/listeners/FinalStatusListener.java new file mode 100644 index 0000000000..0f85f620c8 --- /dev/null +++ b/tools/dexfuzz/src/dexfuzz/listeners/FinalStatusListener.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 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 java.util.List; +import java.util.Map; + +import dexfuzz.executors.Executor; + +/** + * Counts divergences as they appear and checks if the testing was successful + * or not. Testing is successful if all divergences found are either self + * divergent or caused by differences in architectures. + */ +public class FinalStatusListener extends BaseListener { + private long divergence; + private long selfDivergent; + private long architectureSplit; + + @Override + public void handleDivergences(Map<String, List<Executor>> outputMap) { + divergence++; + } + + @Override + public void handleSelfDivergence() { + selfDivergent++; + } + + @Override + public void handleArchitectureSplit() { + architectureSplit++; + } + + public boolean isSuccessful() { + return (divergence - selfDivergent - architectureSplit) == 0; + } +} diff --git a/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java b/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java index 650501be12..5335d1592d 100644 --- a/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java +++ b/tools/dexfuzz/src/dexfuzz/program/CodeTranslator.java @@ -259,8 +259,15 @@ public class CodeTranslator { // Get the MInsns that form the start and end of the try block. int startLocation = tryItem.startAddr; mTryBlock.startInsn = insnLocationMap.get(startLocation); - int endLocation = tryItem.startAddr + tryItem.insnCount; + + // The instructions vary in size, so we have to find the last instruction in the block in a + // few tries. + int endLocation = tryItem.startAddr + tryItem.insnCount - 1; mTryBlock.endInsn = insnLocationMap.get(endLocation); + while ((mTryBlock.endInsn == null) && (endLocation >= startLocation)) { + endLocation--; + mTryBlock.endInsn = insnLocationMap.get(endLocation); + } // Sanity checks. if (mTryBlock.startInsn == null) { @@ -356,8 +363,9 @@ public class CodeTranslator { TryItem tryItem = codeItem.tries[tryItemIdx]; tryItem.startAddr = mTryBlock.startInsn.location; - tryItem.insnCount = - (short) (mTryBlock.endInsn.location - mTryBlock.startInsn.location); + int insnCount = mTryBlock.endInsn.location - mTryBlock.startInsn.location + + mTryBlock.endInsn.insn.getSize(); + tryItem.insnCount = (short) insnCount; // Get the EncodedCatchHandler. EncodedCatchHandler encodedCatchHandler = diff --git a/tools/dexfuzz/src/dexfuzz/program/mutators/TryBlockShifter.java b/tools/dexfuzz/src/dexfuzz/program/mutators/TryBlockShifter.java index 1bf64637cb..55e3e60312 100644 --- a/tools/dexfuzz/src/dexfuzz/program/mutators/TryBlockShifter.java +++ b/tools/dexfuzz/src/dexfuzz/program/mutators/TryBlockShifter.java @@ -81,12 +81,15 @@ public class TryBlockShifter extends CodeMutator { @Override protected boolean canMutate(MutatableCode mutatableCode) { - if (mutatableCode.triesSize > 0) { - return true; + if (mutatableCode.triesSize == 0) { + Log.debug("Method contains no tries."); + return false; } - - Log.debug("Method contains no tries."); - return false; + if (mutatableCode.getInstructionCount() <= 1) { + Log.debug("Not enough instructions to shift try block."); + return false; + } + return true; } @Override diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/DebugInfoItem.java b/tools/dexfuzz/src/dexfuzz/rawdex/DebugInfoItem.java index 922ee5884d..561e9863a0 100644 --- a/tools/dexfuzz/src/dexfuzz/rawdex/DebugInfoItem.java +++ b/tools/dexfuzz/src/dexfuzz/rawdex/DebugInfoItem.java @@ -16,6 +16,8 @@ package dexfuzz.rawdex; +import dexfuzz.Log; + import java.io.IOException; // Right now we are not parsing debug_info_item, just take the raw size @@ -32,6 +34,11 @@ public class DebugInfoItem implements RawDexObject { file.getOffsetTracker().getNewOffsettable(file, this); data = new byte[size]; file.read(data); + + // Since we are not parsing the section, ensure that the last byte is DBG_END_SEQUENCE. + if (data[size - 1] != 0) { + Log.errorAndQuit("Error reading debug_info_item. The last byte is not DBG_END_SEQUENCE."); + } } @Override diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/MapList.java b/tools/dexfuzz/src/dexfuzz/rawdex/MapList.java index 080b5a46bb..729aa715b5 100644 --- a/tools/dexfuzz/src/dexfuzz/rawdex/MapList.java +++ b/tools/dexfuzz/src/dexfuzz/rawdex/MapList.java @@ -162,10 +162,15 @@ public class MapList implements RawDexObject { case MapItem.TYPE_DEBUG_INFO_ITEM: { // We aren't interested in updating the debug data, so just read it as a blob. - int start = mapItem.offset.getOriginalOffset(); - int end = mapItems.get(mapItemIdx + 1).offset.getOriginalOffset(); - int size = end - start; - rawDexFile.debugInfoItem = new DebugInfoItem(size); + long start = mapItem.offset.getOriginalOffset(); + long end = 0; + if (mapItemIdx + 1 == mapItems.size()) { + end = file.length(); + } else { + end = mapItems.get(mapItemIdx + 1).offset.getOriginalOffset(); + } + long size = end - start; + rawDexFile.debugInfoItem = new DebugInfoItem((int)size); rawDexFile.debugInfoItem.read(file); break; } |