Assign temporary register to the size of an array.
Temporary register was added so that the value of existing registers
could remain the same.
Test: Dexfuzz was run.
Before
000144: 1300 0800 |0000: const/16 v0, #int 8 // #8
000148: 2300 0300 |0002: new-array v0, v0, [I // type@0003
00014c: 2600 0400 0000 |0004: fill-array-data v0, 00000008 // +00000004
000152: 1100 |0007: return-object v0
After
000144: 0900 0100 0200 |0000: move-object/16 v1, v2
00014a: 1300 1052 |0003: const/16 v0, #int 21008 // #5210
00014e: 1302 1800 |0005: const/16 v2, #int 24 // #18
000152: 2320 0300 |0007: new-array v0, v2, [I // type@0003
000156: 2600 0500 0000 |0009: fill-array-data v0, 0000000e // +00000005
00015c: 1102 |000c: return-object v2
Change-Id: I0d8380ab3facd6256bc46931929d32763bad4476
diff --git a/tools/dexfuzz/src/dexfuzz/DexFuzz.java b/tools/dexfuzz/src/dexfuzz/DexFuzz.java
index d37bd34..b0ce5a8 100644
--- a/tools/dexfuzz/src/dexfuzz/DexFuzz.java
+++ b/tools/dexfuzz/src/dexfuzz/DexFuzz.java
@@ -33,9 +33,9 @@
* Entrypoint class for dexfuzz.
*/
public class DexFuzz {
- // Last version update 1.5: added register clobber mutator.
+ // Last version update 1.6: added temporary register to ArrayLengthChanger.
private static int majorVersion = 1;
- private static int minorVersion = 5;
+ private static int minorVersion = 6;
private static int seedChangeVersion = 0;
/**
diff --git a/tools/dexfuzz/src/dexfuzz/program/mutators/NewArrayLengthChanger.java b/tools/dexfuzz/src/dexfuzz/program/mutators/NewArrayLengthChanger.java
index aba7971..e640b4e 100644
--- a/tools/dexfuzz/src/dexfuzz/program/mutators/NewArrayLengthChanger.java
+++ b/tools/dexfuzz/src/dexfuzz/program/mutators/NewArrayLengthChanger.java
@@ -28,8 +28,6 @@
import java.util.List;
import java.util.Random;
-// This mutation might change the length of an array but can also change the
-// value of the register in every place it is used.
public class NewArrayLengthChanger extends CodeMutator {
/**
* Every CodeMutator has an AssociatedMutation, representing the
@@ -116,20 +114,46 @@
MutatableCode mutatableCode = mutation.mutatableCode;
MInsn newArrayInsn = newArrayLengthInsns.get(mutation.newArrayToChangeIdx);
int newArrayInsnIdx = mutatableCode.getInstructionIndex(newArrayInsn);
+ // If the original new-array instruction is no longer present
+ // in the code (as indicated by a negative index), we make a
+ // best effort to find any other new-array instruction to
+ // apply the mutation to. If that effort fails, we simply
+ // bail by doing nothing.
+ if (newArrayInsnIdx < 0) {
+ newArrayInsnIdx = scanNewArray(mutatableCode);
+ if (newArrayInsnIdx == -1) {
+ return;
+ }
+ }
MInsn newInsn = new MInsn();
newInsn.insn = new Instruction();
newInsn.insn.info = Instruction.getOpcodeInfo(Opcode.CONST_16);
+ mutatableCode.allocateTemporaryVRegs(1);
+ newArrayInsn.insn.vregB = mutatableCode.getTemporaryVReg(0);
newInsn.insn.vregA = (int) newArrayInsn.insn.vregB;
// New length chosen randomly between 1 to 100.
newInsn.insn.vregB = rng.nextInt(100);
mutatableCode.insertInstructionAt(newInsn, newArrayInsnIdx);
Log.info("Changed the length of the array to " + newInsn.insn.vregB);
stats.incrementStat("Changed length of new array");
+ mutatableCode.finishedUsingTemporaryVRegs();
}
private boolean isNewArray(MInsn mInsn) {
Opcode opcode = mInsn.insn.info.opcode;
return opcode == Opcode.NEW_ARRAY;
}
+
+ // Return the index of first new-array in the method, -1 otherwise.
+ private int scanNewArray(MutatableCode mutatableCode) {
+ int idx = 0;
+ for (MInsn mInsn : mutatableCode.getInstructions()) {
+ if (isNewArray(mInsn)) {
+ return idx;
+ }
+ idx++;
+ }
+ return -1;
+ }
}
\ No newline at end of file