1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package dexfuzz.program.mutators; 18 19import dexfuzz.Log; 20import dexfuzz.MutationStats; 21import dexfuzz.Options; 22import dexfuzz.program.MutatableCode; 23import dexfuzz.program.Mutation; 24 25import java.util.List; 26import java.util.Random; 27 28/** 29 * The base class for all classes that can mutate methods. 30 */ 31public abstract class CodeMutator { 32 /** 33 * The RNG, passed in by the Program that initialised us. 34 */ 35 protected Random rng; 36 37 /** 38 * Used to track which mutations happen. 39 */ 40 protected MutationStats stats; 41 42 /** 43 * Used to track mutations that have been applied so far. 44 */ 45 protected List<Mutation> mutations; 46 47 /** 48 * The chance, out of 100, that this mutator actually mutates the the program 49 * when asked to by the Program. The default is 50% chance, but each mutator that 50 * extends CodeMutator should its own default. 51 */ 52 protected int likelihood = 50; 53 54 /** 55 * This constructor is only intended for use in MutationRecorder... 56 */ 57 public CodeMutator() { 58 59 } 60 61 /** 62 * Constructor that all subclasses must call... 63 * 64 * @param rng The RNG that the Program created. 65 */ 66 public CodeMutator(Random rng, MutationStats stats, List<Mutation> mutations) { 67 this.rng = rng; 68 this.stats = stats; 69 this.mutations = mutations; 70 71 String name = this.getClass().getSimpleName().toLowerCase(); 72 73 if (Options.mutationLikelihoods.containsKey(name)) { 74 likelihood = Options.mutationLikelihoods.get(name); 75 Log.info("Set mutation likelihood to " + likelihood 76 + "% for " + this.getClass().getSimpleName()); 77 } 78 } 79 80 /** 81 * When the Program picks a particular mutator to mutate the code, it calls 82 * this function, that determines if the mutator will actually mutate the code. 83 * If so, it then calls the mutationFunction() method, that every subclass CodeMutator 84 * is expected to implement to perform its mutation. 85 * 86 * @return If mutation took place. 87 */ 88 public boolean attemptToMutate(MutatableCode mutatableCode) { 89 if (shouldMutate(mutatableCode)) { 90 generateAndApplyMutation(mutatableCode); 91 return true; 92 } 93 Log.info("Skipping mutation."); 94 return false; 95 } 96 97 public void forceMutate(Mutation mutation) { 98 Log.info("Forcing mutation."); 99 applyMutation(mutation); 100 } 101 102 public boolean canBeTriggered() { 103 return (likelihood > 0); 104 } 105 106 /** 107 * Randomly determine if the mutator will actually mutate a method, based on its 108 * provided likelihood of mutation. 109 * 110 * @return If the method should be mutated. 111 */ 112 private boolean shouldMutate(MutatableCode mutatableCode) { 113 return ((rng.nextInt(100) < likelihood) && canMutate(mutatableCode)); 114 } 115 116 private void generateAndApplyMutation(MutatableCode mutatableCode) { 117 Mutation mutation = generateMutation(mutatableCode); 118 // Always save the mutation. 119 mutations.add(mutation); 120 applyMutation(mutation); 121 } 122 123 /** 124 * A CodeMutator must override this method if there is any reason why could not mutate 125 * a particular method, and return false in that case. 126 */ 127 protected boolean canMutate(MutatableCode mutatableCode) { 128 return true; 129 } 130 131 protected abstract Mutation generateMutation(MutatableCode mutatableCode); 132 133 protected abstract void applyMutation(Mutation uncastMutation); 134 135 public abstract Mutation getNewMutation(); 136} 137