1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/* 2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project 3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License"); 5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License. 6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at 7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * http://www.apache.org/licenses/LICENSE-2.0 9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software 11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS, 12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and 14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License. 15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz.program.mutators; 18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log; 20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.MutationStats; 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.MInsn; 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.MutatableCode; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.Mutation; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.Random; 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class InstructionSwapper extends CodeMutator { 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Every CodeMutator has an AssociatedMutation, representing the 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * mutation that this CodeMutator can perform, to allow separate 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * generateMutation() and applyMutation() phases, allowing serialization. 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static class AssociatedMutation extends Mutation { 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int swapInsnIdx; 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int swapWithInsnIdx; 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public String getString() { 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle StringBuilder builder = new StringBuilder(); 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle builder.append(swapInsnIdx).append(" "); 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle builder.append(swapWithInsnIdx); 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return builder.toString(); 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void parseString(String[] elements) { 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle swapInsnIdx = Integer.parseInt(elements[2]); 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle swapWithInsnIdx = Integer.parseInt(elements[3]); 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // The following two methods are here for the benefit of MutationSerializer, 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // so it can create a CodeMutator and get the correct associated Mutation, as it 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // reads in mutations from a dump of mutations. 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public Mutation getNewMutation() { 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return new AssociatedMutation(); 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public InstructionSwapper() { } 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public InstructionSwapper(Random rng, MutationStats stats, List<Mutation> mutations) { 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle super(rng, stats, mutations); 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle likelihood = 80; 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected boolean canMutate(MutatableCode mutatableCode) { 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mutatableCode.getInstructionCount() == 1) { 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Cannot swap one instruction. 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Cannot swap insns in a method with only one."); 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return true; 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected Mutation generateMutation(MutatableCode mutatableCode) { 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int swapInsnIdx = 0; 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int swapWithInsnIdx = 0; 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle boolean foundFirstInsn = false; 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle boolean foundSecondInsn = false; 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (!foundFirstInsn || !foundSecondInsn) { 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Look for the first insn. 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (!foundFirstInsn) { 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle swapInsnIdx = rng.nextInt(mutatableCode.getInstructionCount()); 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MInsn toBeSwapped = mutatableCode.getInstructionAt(swapInsnIdx); 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundFirstInsn = true; 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (toBeSwapped.insn.justRaw) { 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundFirstInsn = false; 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Look for the second insn. 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int secondInsnAttempts = 0; 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (!foundSecondInsn) { 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int delta = rng.nextInt(5) - 1; 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (delta == 0) { 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle continue; 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle swapWithInsnIdx = swapInsnIdx + delta; 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundSecondInsn = true; 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Check insn is in valid range. 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (swapWithInsnIdx < 0) { 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundSecondInsn = false; 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (swapWithInsnIdx >= mutatableCode.getInstructionCount()) { 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundSecondInsn = false; 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Finally, check if we're swapping with a raw insn. 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (foundSecondInsn) { 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mutatableCode.getInstructionAt(swapWithInsnIdx).insn.justRaw) { 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundSecondInsn = false; 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // If we've checked 10 times for an insn to swap with, 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // and still found nothing, then try a new first insn. 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!foundSecondInsn) { 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle secondInsnAttempts++; 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (secondInsnAttempts == 10) { 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle foundFirstInsn = false; 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle break; 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle AssociatedMutation mutation = new AssociatedMutation(); 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.setup(this.getClass(), mutatableCode); 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.swapInsnIdx = swapInsnIdx; 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.swapWithInsnIdx = swapWithInsnIdx; 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return mutation; 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected void applyMutation(Mutation uncastMutation) { 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Cast the Mutation to our AssociatedMutation, so we can access its fields. 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle AssociatedMutation mutation = (AssociatedMutation) uncastMutation; 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MutatableCode mutatableCode = mutation.mutatableCode; 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MInsn toBeSwapped = mutatableCode.getInstructionAt(mutation.swapInsnIdx); 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MInsn swappedWith = mutatableCode.getInstructionAt(mutation.swapWithInsnIdx); 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.info("Swapping " + toBeSwapped + " with " + swappedWith); 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle stats.incrementStat("Swapped two instructions"); 154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutatableCode.swapInstructionsByIndex(mutation.swapInsnIdx, mutation.swapWithInsnIdx); 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.info("Now " + swappedWith + " is swapped with " + toBeSwapped); 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 160