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