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.Instruction;
25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.rawdex.Opcode;
26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.ArrayList;
28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List;
29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.Random;
30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class ConversionRepeater extends CodeMutator {
32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Every CodeMutator has an AssociatedMutation, representing the
34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * mutation that this CodeMutator can perform, to allow separate
35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * generateMutation() and applyMutation() phases, allowing serialization.
36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public static class AssociatedMutation extends Mutation {
38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public int conversionInsnIdx;
39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    @Override
41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public String getString() {
42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return Integer.toString(conversionInsnIdx);
43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    @Override
46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public void parseString(String[] elements) {
47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      conversionInsnIdx = Integer.parseInt(elements[2]);
48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // The following two methods are here for the benefit of MutationSerializer,
52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // so it can create a CodeMutator and get the correct associated Mutation, as it
53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // reads in mutations from a dump of mutations.
54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public Mutation getNewMutation() {
56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return new AssociatedMutation();
57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public ConversionRepeater() { }
60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public ConversionRepeater(Random rng, MutationStats stats, List<Mutation> mutations) {
62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    super(rng, stats, mutations);
63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    likelihood = 50;
64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // A cache that should only exist between generateMutation() and applyMutation(),
67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // or be created at the start of applyMutation(), if we're reading in mutations from
68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // a file.
69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private List<MInsn> conversionInsns = null;
70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private void generateCachedConversionInsns(MutatableCode mutatableCode) {
72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (conversionInsns != null) {
73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return;
74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    conversionInsns = new ArrayList<MInsn>();
77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    for (MInsn mInsn : mutatableCode.getInstructions()) {
79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      if (isConversionInstruction(mInsn)) {
80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        conversionInsns.add(mInsn);
81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected boolean canMutate(MutatableCode mutatableCode) {
87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    for (MInsn mInsn : mutatableCode.getInstructions()) {
88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      if (isConversionInstruction(mInsn)) {
89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        return true;
90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    Log.debug("No conversion operations in method, skipping...");
94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return false;
95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected Mutation generateMutation(MutatableCode mutatableCode) {
99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    generateCachedConversionInsns(mutatableCode);
100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int conversionInsnIdx = rng.nextInt(conversionInsns.size());
101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    AssociatedMutation mutation = new AssociatedMutation();
102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.setup(this.getClass(), mutatableCode);
103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.conversionInsnIdx = conversionInsnIdx;
104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return mutation;
105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected void applyMutation(Mutation uncastMutation) {
109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Cast the Mutation to our AssociatedMutation, so we can access its fields.
110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    AssociatedMutation mutation = (AssociatedMutation) uncastMutation;
111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MutatableCode mutatableCode = mutation.mutatableCode;
112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    generateCachedConversionInsns(mutatableCode);
114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MInsn originalInsn = conversionInsns.get(mutation.conversionInsnIdx);
116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // We want to create two new instructions:
118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // [original conversion] eg float-to-int
119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // NEW: [there] eg int-to-float (with vregs of first inst swapped)
120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // NEW: [back] eg float-to-int
121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Create the "there" instruction.
123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MInsn newInsnThere = originalInsn.clone();
124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Flip the opcode.
126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    Opcode oppositeOpcode = null;
127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    switch (newInsnThere.insn.info.opcode) {
128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case INT_TO_LONG:
129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.LONG_TO_INT;
130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case INT_TO_FLOAT:
132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.FLOAT_TO_INT;
133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case INT_TO_DOUBLE:
135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.DOUBLE_TO_INT;
136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case LONG_TO_INT:
138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.INT_TO_LONG;
139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case LONG_TO_FLOAT:
141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.FLOAT_TO_LONG;
142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case LONG_TO_DOUBLE:
144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.DOUBLE_TO_LONG;
145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case FLOAT_TO_INT:
147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.INT_TO_FLOAT;
148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case FLOAT_TO_LONG:
150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.LONG_TO_FLOAT;
151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case FLOAT_TO_DOUBLE:
153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.DOUBLE_TO_FLOAT;
154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case DOUBLE_TO_INT:
156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.INT_TO_DOUBLE;
157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case DOUBLE_TO_LONG:
159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.LONG_TO_DOUBLE;
160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      case DOUBLE_TO_FLOAT:
162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        oppositeOpcode = Opcode.FLOAT_TO_DOUBLE;
163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        break;
164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      default:
165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        Log.errorAndQuit(
166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle            "Trying to repeat the conversion in an insn that is not a conversion insn.");
167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    newInsnThere.insn.info = Instruction.getOpcodeInfo(oppositeOpcode);
169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Swap the vregs.
171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    long tempReg = newInsnThere.insn.vregA;
172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    newInsnThere.insn.vregA = newInsnThere.insn.vregB;
173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    newInsnThere.insn.vregB = tempReg;
174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Create the "back" instruction.
176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MInsn newInsnBack = originalInsn.clone();
177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Get the index into the MutatableCode's mInsns list for this insn.
179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int originalInsnIdx = mutatableCode.getInstructionIndex(originalInsn);
180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Insert the new instructions.
182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutatableCode.insertInstructionAfter(newInsnThere, originalInsnIdx);
183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutatableCode.insertInstructionAfter(newInsnBack, originalInsnIdx + 1);
184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    Log.info("Performing conversion repetition for " + originalInsn);
186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    stats.incrementStat("Repeating conversion");
188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Clear the cache.
190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    conversionInsns = null;
191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private boolean isConversionInstruction(MInsn mInsn) {
194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    Opcode opcode = mInsn.insn.info.opcode;
195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (Opcode.isBetween(opcode, Opcode.INT_TO_LONG, Opcode.DOUBLE_TO_FLOAT)) {
196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return true;
197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return false;
199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle}
201