From 422b10b419eb010b612931e8b250b9dd1b7424ed Mon Sep 17 00:00:00 2001 From: Runemoro Date: Sat, 2 Nov 2019 17:23:14 -0400 Subject: Check protected method/field target in visibility index (#157) --- .../cuchaz/enigma/analysis/InterpreterPair.java | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/main/java/cuchaz/enigma/analysis/InterpreterPair.java (limited to 'src/main/java/cuchaz/enigma/analysis/InterpreterPair.java') diff --git a/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java b/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java new file mode 100644 index 0000000..af74c85 --- /dev/null +++ b/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java @@ -0,0 +1,138 @@ +package cuchaz.enigma.analysis; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.analysis.AnalyzerException; +import org.objectweb.asm.tree.analysis.Interpreter; +import org.objectweb.asm.tree.analysis.Value; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class InterpreterPair extends Interpreter> { + private final Interpreter left; + private final Interpreter right; + + public InterpreterPair(Interpreter left, Interpreter right) { + super(Opcodes.ASM7); + this.left = left; + this.right = right; + } + + @Override + public PairValue newValue(Type type) { + return pair( + left.newValue(type), + right.newValue(type) + ); + } + + @Override + public PairValue newOperation(AbstractInsnNode insn) throws AnalyzerException { + return pair( + left.newOperation(insn), + right.newOperation(insn) + ); + } + + @Override + public PairValue copyOperation(AbstractInsnNode insn, PairValue value) throws AnalyzerException { + return pair( + left.copyOperation(insn, value.left), + right.copyOperation(insn, value.right) + ); + } + + @Override + public PairValue unaryOperation(AbstractInsnNode insn, PairValue value) throws AnalyzerException { + return pair( + left.unaryOperation(insn, value.left), + right.unaryOperation(insn, value.right) + ); + } + + @Override + public PairValue binaryOperation(AbstractInsnNode insn, PairValue value1, PairValue value2) throws AnalyzerException { + return pair( + left.binaryOperation(insn, value1.left, value2.left), + right.binaryOperation(insn, value1.right, value2.right) + ); + } + + @Override + public PairValue ternaryOperation(AbstractInsnNode insn, PairValue value1, PairValue value2, PairValue value3) throws AnalyzerException { + return pair( + left.ternaryOperation(insn, value1.left, value2.left, value3.left), + right.ternaryOperation(insn, value1.right, value2.right, value3.right) + ); + } + + @Override + public PairValue naryOperation(AbstractInsnNode insn, List> values) throws AnalyzerException { + return pair( + left.naryOperation(insn, values.stream().map(v -> v.left).collect(Collectors.toList())), + right.naryOperation(insn, values.stream().map(v -> v.right).collect(Collectors.toList())) + ); + } + + @Override + public void returnOperation(AbstractInsnNode insn, PairValue value, PairValue expected) throws AnalyzerException { + left.returnOperation(insn, value.left, expected.left); + right.returnOperation(insn, value.right, expected.right); + } + + @Override + public PairValue merge(PairValue value1, PairValue value2) { + return pair( + left.merge(value1.left, value2.left), + right.merge(value1.right, value2.right) + ); + } + + private PairValue pair(V left, W right) { + if (left == null && right == null) { + return null; + } + + if (left != null && right != null && left.getSize() != right.getSize()) { + throw new IllegalStateException("sizes don't match"); + } + + return new PairValue<>(left, right); + } + + public static final class PairValue implements Value { + public final V left; + public final W right; + + public PairValue(V left, W right) { + if (left == null && right == null) { + throw new IllegalArgumentException("should use null rather than pair of nulls"); + } + + if (left != null && right != null && left.getSize() != right.getSize()) { + throw new IllegalArgumentException("sizes don't match"); + } + + this.left = left; + this.right = right; + } + + @Override + public boolean equals(Object o) { + return o instanceof InterpreterPair.PairValue && Objects.equals(left, ((PairValue) o).left) && Objects.equals(right, ((PairValue) o).right); + } + + @Override + public int hashCode() { + return left.hashCode() * 31 + right.hashCode(); + } + + @Override + public int getSize() { + return (left == null ? right : left).getSize(); + } + } +} -- cgit v1.2.3