Skip to content

Commit f38dda2

Browse files
authored
Merge pull request #1434 from hcoles/feature/deprecate_unsafe_index_access
deprecate unsafe instruction index access
2 parents 6903f7c + 2b46189 commit f38dda2

File tree

8 files changed

+49
-13
lines changed

8 files changed

+49
-13
lines changed

pitest-entry/src/main/java/org/pitest/bytecode/analysis/MethodTree.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.ArrayList;
44
import java.util.List;
5+
import java.util.Optional;
56

67
import org.objectweb.asm.Opcodes;
78
import org.objectweb.asm.tree.AbstractInsnNode;
@@ -34,16 +35,25 @@ public Location asLocation() {
3435
* @param index index to work backwards from
3536
* @return The previous instruction
3637
*/
38+
@Deprecated
3739
public AbstractInsnNode realInstructionBefore(int index) {
3840
AbstractInsnNode candidate = instructions().get(index - 1);
3941
if (candidate.getOpcode() == -1) {
4042
return realInstructionBefore(index - 1);
4143
}
4244
return candidate;
4345
}
44-
46+
47+
public Optional<AbstractInsnNode> instructionForIndex(int index) {
48+
return Optional.ofNullable(instruction(index));
49+
}
50+
51+
@Deprecated
4552
public AbstractInsnNode instruction(int index) {
46-
return instructions().get(index);
53+
if (index < 0 || index >= instructions().size() ) {
54+
return null;
55+
}
56+
return instructions().get(index);
4757
}
4858

4959
public List<AbstractInsnNode> instructions() {

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/equivalent/EqualsPerformanceShortcutFilter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ private boolean shortCutEquals(MethodTree tree, MutationDetails a, Mutater m) {
112112
}
113113

114114
private boolean mutatesAConditionalJump(MethodTree tree, int index) {
115-
final AbstractInsnNode mutatedInsns = tree.instruction(index);
116-
return InstructionMatchers.aConditionalJump().asPredicate().test(mutatedInsns);
115+
var mutatedInsns = tree.instructionForIndex(index);
116+
return mutatedInsns
117+
.map(n -> InstructionMatchers.aConditionalJump().asPredicate().test(n))
118+
.orElse(false);
117119
}
118120

119121
private Predicate<MutationDetails> inEqualsMethod() {

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/javafeatures/ForEachLoopFilter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,14 @@ private Predicate<MutationDetails> mutatesIteratorLoopPlumbing() {
202202
return false;
203203
}
204204

205-
final AbstractInsnNode mutatedInstruction = method.instruction(instruction);
205+
var mutatedInstruction = method.instructionForIndex(instruction);
206+
if (mutatedInstruction.isEmpty()) {
207+
return false;
208+
}
206209

207210
Set<AbstractInsnNode> toAvoid = cache.computeIfAbsent(method, this::findLoopInstructions);
208211

209-
return toAvoid.contains(mutatedInstruction);
212+
return toAvoid.contains(mutatedInstruction.get());
210213
};
211214
}
212215

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/javafeatures/InlinedFinallyBlockFilter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,13 @@ private boolean isInFinallyBlock(MutationDetails m) {
184184
return false;
185185
}
186186

187-
AbstractInsnNode mutatedInstruction = method.instruction(m.getInstructionIndex());
187+
var mutatedInstruction = method.instructionForIndex(m.getInstructionIndex());
188+
if (mutatedInstruction.isEmpty()) {
189+
return false;
190+
}
188191

189192
Context context = Context.start(DEBUG);
190-
context = context.store(MUTATED_INSTRUCTION.write(), mutatedInstruction);
193+
context = context.store(MUTATED_INSTRUCTION.write(), mutatedInstruction.get());
191194
context = context.store(HANDLERS.write(), handlers);
192195
return IS_IN_HANDLER.matches(method.instructions(), context);
193196
}

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/timeout/AvoidForLoopCounterFilter.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,12 @@ private Predicate<MutationDetails> mutatesAForLoopCounter() {
170170
return false;
171171
}
172172

173-
final AbstractInsnNode mutatedInstruction = method.instruction(instruction);
173+
var maybeIns = method.instructionForIndex(instruction);
174+
if (maybeIns.isEmpty()) {
175+
return false;
176+
}
177+
178+
var mutatedInstruction = maybeIns.get();
174179

175180
// performance hack
176181
if (!(mutatedInstruction instanceof IincInsnNode)) {

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/timeout/InfiniteForLoopFilter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ SequenceMatcher<AbstractInsnNode> infiniteLoopMatcher() {
5353

5454
@Override
5555
boolean couldCauseInfiniteLoop(MethodTree method, MutationDetails each) {
56-
final AbstractInsnNode instruction = method.instruction(each.getInstructionIndex());
57-
return instruction.getOpcode() == Opcodes.IINC;
56+
var instruction = method.instructionForIndex(each.getInstructionIndex());
57+
return instruction
58+
.map(i -> i.getOpcode() == Opcodes.IINC)
59+
.orElse(false);
5860
}
5961

6062
private static SequenceQuery<AbstractInsnNode> countingLoopWithoutWriteConditionalAtStart() {

pitest-entry/src/main/java/org/pitest/mutationtest/build/intercept/timeout/InfiniteIteratorLoopFilter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ SequenceMatcher<AbstractInsnNode> infiniteLoopMatcher() {
4444

4545
@Override
4646
boolean couldCauseInfiniteLoop(MethodTree method, MutationDetails each) {
47-
final AbstractInsnNode instruction = method.instruction(each.getInstructionIndex());
48-
return isIteratorNext(instruction);
47+
var instruction = method.instructionForIndex(each.getInstructionIndex());
48+
return instruction
49+
.map(this::isIteratorNext)
50+
.orElse(false);
4951
}
5052

5153
private static SequenceQuery<AbstractInsnNode> doesNotBreakIteratorLoop() {

pitest-entry/src/test/java/org/pitest/bytecode/analysis/MethodTreeTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ public class MethodTreeTest {
99

1010
ClassloaderByteArraySource bytes = ClassloaderByteArraySource.fromContext();
1111

12+
@Test
13+
public void retrievesInstructionsWithinMethod() {
14+
var clazz = loadClass(MethodTreeTest.class.getName());
15+
var method = findMethod(clazz, "retrievesInstructionsWithinMethod");
16+
assertThat(method.instructionForIndex(0)).isNotEmpty();
17+
assertThat(method.instructionForIndex(-1)).isEmpty();
18+
assertThat(method.instructionForIndex(Integer.MAX_VALUE)).isEmpty();
19+
}
20+
1221
@Test
1322
public void recognisesAbstractMethods() {
1423
var clazz = loadClass(Bar.class.getName());

0 commit comments

Comments
 (0)