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 Kyleimport dexfuzz.rawdex.formats.ContainsConst; 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.ArrayList; 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.Random; 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class ConstantValueChanger extends CodeMutator { 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Every CodeMutator has an AssociatedMutation, representing the 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * mutation that this CodeMutator can perform, to allow separate 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * generateMutation() and applyMutation() phases, allowing serialization. 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static class AssociatedMutation extends Mutation { 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public int constInsnIdx; 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public long newConstant; 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public String getString() { 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle StringBuilder builder = new StringBuilder(); 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle builder.append(constInsnIdx).append(" "); 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle builder.append(newConstant); 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return builder.toString(); 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public void parseString(String[] elements) { 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle constInsnIdx = Integer.parseInt(elements[2]); 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle newConstant = Long.parseLong(elements[3]); 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // The following two methods are here for the benefit of MutationSerializer, 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // so it can create a CodeMutator and get the correct associated Mutation, as it 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // reads in mutations from a dump of mutations. 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public Mutation getNewMutation() { 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return new AssociatedMutation(); 61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public ConstantValueChanger() { } 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public ConstantValueChanger(Random rng, MutationStats stats, List<Mutation> mutations) { 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle super(rng, stats, mutations); 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle likelihood = 70; 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // A cache that should only exist between generateMutation() and applyMutation(), 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // or be created at the start of applyMutation(), if we're reading in mutations from 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // a file. 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private List<MInsn> constInsns = null; 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private void generateCachedConstInsns(MutatableCode mutatableCode) { 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (constInsns != null) { 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return; 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle constInsns = new ArrayList<MInsn>(); 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MInsn mInsn : mutatableCode.getInstructions()) { 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mInsn.insn.info.format instanceof ContainsConst) { 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle constInsns.add(mInsn); 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected boolean canMutate(MutatableCode mutatableCode) { 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (MInsn mInsn : mutatableCode.getInstructions()) { 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mInsn.insn.info.format instanceof ContainsConst) { 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return true; 93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.debug("Method contains no const instructions."); 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected Mutation generateMutation(MutatableCode mutatableCode) { 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle generateCachedConstInsns(mutatableCode); 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Pick a random const instruction. 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int constInsnIdx = rng.nextInt(constInsns.size()); 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MInsn constInsn = constInsns.get(constInsnIdx); 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Get the constant. 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long oldConstant = ((ContainsConst)constInsn.insn.info.format).getConst(constInsn.insn); 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long newConstant = oldConstant; 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Make a new constant. 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (newConstant == oldConstant) { 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle newConstant = rng.nextLong() 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle % ((ContainsConst)constInsn.insn.info.format).getConstRange(); 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle AssociatedMutation mutation = new AssociatedMutation(); 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.setup(this.getClass(), mutatableCode); 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.constInsnIdx = constInsnIdx; 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutation.newConstant = newConstant; 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return mutation; 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle @Override 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle protected void applyMutation(Mutation uncastMutation) { 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Cast the Mutation to our AssociatedMutation, so we can access its fields. 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle AssociatedMutation mutation = (AssociatedMutation) uncastMutation; 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MutatableCode mutatableCode = mutation.mutatableCode; 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle generateCachedConstInsns(mutatableCode); 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle MInsn constInsn = constInsns.get(mutation.constInsnIdx); 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle long oldConstant = ((ContainsConst)constInsn.insn.info.format).getConst(constInsn.insn); 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.info("Changed constant value #" + oldConstant + " to #" + mutation.newConstant 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle + " in " + constInsn); 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle stats.incrementStat("Changed constant value"); 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Set the new constant. 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle ((ContainsConst)constInsn.insn.info.format).setConst(constInsn.insn, mutation.newConstant); 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Clear cache. 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle constInsns = null; 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 150