diff options
Diffstat (limited to 'tools/dexfuzz/src/dexfuzz/program/mutators/CodeMutator.java')
-rw-r--r-- | tools/dexfuzz/src/dexfuzz/program/mutators/CodeMutator.java | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/tools/dexfuzz/src/dexfuzz/program/mutators/CodeMutator.java b/tools/dexfuzz/src/dexfuzz/program/mutators/CodeMutator.java new file mode 100644 index 0000000..be566ad --- /dev/null +++ b/tools/dexfuzz/src/dexfuzz/program/mutators/CodeMutator.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2014 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.program.mutators; + +import dexfuzz.Log; +import dexfuzz.MutationStats; +import dexfuzz.Options; +import dexfuzz.program.MutatableCode; +import dexfuzz.program.Mutation; + +import java.util.List; +import java.util.Random; + +/** + * The base class for all classes that can mutate methods. + */ +public abstract class CodeMutator { + /** + * The RNG, passed in by the Program that initialised us. + */ + protected Random rng; + + /** + * Used to track which mutations happen. + */ + protected MutationStats stats; + + /** + * Used to track mutations that have been applied so far. + */ + protected List<Mutation> mutations; + + /** + * The chance, out of 100, that this mutator actually mutates the the program + * when asked to by the Program. The default is 50% chance, but each mutator that + * extends CodeMutator should its own default. + */ + protected int likelihood = 50; + + /** + * This constructor is only intended for use in MutationRecorder... + */ + public CodeMutator() { + + } + + /** + * Constructor that all subclasses must call... + * + * @param rng The RNG that the Program created. + */ + public CodeMutator(Random rng, MutationStats stats, List<Mutation> mutations) { + this.rng = rng; + this.stats = stats; + this.mutations = mutations; + + String name = this.getClass().getSimpleName().toLowerCase(); + + if (Options.mutationLikelihoods.containsKey(name)) { + likelihood = Options.mutationLikelihoods.get(name); + Log.info("Set mutation likelihood to " + likelihood + + "% for " + this.getClass().getSimpleName()); + } + } + + /** + * When the Program picks a particular mutator to mutate the code, it calls + * this function, that determines if the mutator will actually mutate the code. + * If so, it then calls the mutationFunction() method, that every subclass CodeMutator + * is expected to implement to perform its mutation. + * + * @return If mutation took place. + */ + public boolean attemptToMutate(MutatableCode mutatableCode) { + if (shouldMutate(mutatableCode)) { + generateAndApplyMutation(mutatableCode); + return true; + } + Log.info("Skipping mutation."); + return false; + } + + public void forceMutate(Mutation mutation) { + Log.info("Forcing mutation."); + applyMutation(mutation); + } + + public boolean canBeTriggered() { + return (likelihood > 0); + } + + /** + * Randomly determine if the mutator will actually mutate a method, based on its + * provided likelihood of mutation. + * + * @return If the method should be mutated. + */ + private boolean shouldMutate(MutatableCode mutatableCode) { + return ((rng.nextInt(100) < likelihood) && canMutate(mutatableCode)); + } + + private void generateAndApplyMutation(MutatableCode mutatableCode) { + Mutation mutation = generateMutation(mutatableCode); + // Always save the mutation. + mutations.add(mutation); + applyMutation(mutation); + } + + /** + * A CodeMutator must override this method if there is any reason why could not mutate + * a particular method, and return false in that case. + */ + protected boolean canMutate(MutatableCode mutatableCode) { + return true; + } + + protected abstract Mutation generateMutation(MutatableCode mutatableCode); + + protected abstract void applyMutation(Mutation uncastMutation); + + public abstract Mutation getNewMutation(); +} |