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 
17 package dexfuzz.program.mutators;
18 
19 import dexfuzz.Log;
20 import dexfuzz.MutationStats;
21 import dexfuzz.Options;
22 import dexfuzz.program.MutatableCode;
23 import dexfuzz.program.Mutation;
24 
25 import java.util.List;
26 import java.util.Random;
27 
28 /**
29  * The base class for all classes that can mutate methods.
30  */
31 public 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    */
CodeMutator()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    */
CodeMutator(Random rng, MutationStats stats, List<Mutation> mutations)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    */
attemptToMutate(MutatableCode mutatableCode)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 
forceMutate(Mutation mutation)97   public void forceMutate(Mutation mutation) {
98     Log.info("Forcing mutation.");
99     applyMutation(mutation);
100   }
101 
canBeTriggered()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    */
shouldMutate(MutatableCode mutatableCode)112   private boolean shouldMutate(MutatableCode mutatableCode) {
113     return ((rng.nextInt(100) < likelihood) && canMutate(mutatableCode));
114   }
115 
generateAndApplyMutation(MutatableCode mutatableCode)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    */
canMutate(MutatableCode mutatableCode)127   protected boolean canMutate(MutatableCode mutatableCode) {
128     return true;
129   }
130 
generateMutation(MutatableCode mutatableCode)131   protected abstract Mutation generateMutation(MutatableCode mutatableCode);
132 
applyMutation(Mutation uncastMutation)133   protected abstract void applyMutation(Mutation uncastMutation);
134 
getNewMutation()135   public abstract Mutation getNewMutation();
136 }
137