core: fix duplicate regions creation (#314)
This commit is contained in:
@@ -5,7 +5,7 @@ import jadx.core.utils.InsnUtils;
|
||||
|
||||
public class GotoNode extends TargetInsnNode {
|
||||
|
||||
protected int target;
|
||||
protected final int target;
|
||||
|
||||
public GotoNode(int target) {
|
||||
this(InsnType.GOTO, target, 0);
|
||||
|
||||
@@ -47,7 +47,6 @@ public class IfNode extends GotoNode {
|
||||
BlockNode tmp = thenBlock;
|
||||
thenBlock = elseBlock;
|
||||
elseBlock = tmp;
|
||||
target = thenBlock.getStartOffset();
|
||||
}
|
||||
|
||||
public void changeCondition(IfOp op, InsnArg arg1, InsnArg arg2) {
|
||||
@@ -88,6 +87,11 @@ public class IfNode extends GotoNode {
|
||||
return elseBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTarget() {
|
||||
return thenBlock == null ? target : thenBlock.getStartOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSame(InsnNode obj) {
|
||||
if (this == obj) {
|
||||
|
||||
@@ -240,7 +240,6 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
}
|
||||
}
|
||||
this.addAttr(new SourceFileAttr(fileName));
|
||||
LOG.debug("Class '{}' compiled from '{}'", this, fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -486,7 +485,6 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
|
||||
return clsInfo.equals(other.clsInfo);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import jadx.core.dex.nodes.IContainer;
|
||||
import jadx.core.dex.nodes.IRegion;
|
||||
import jadx.core.utils.Utils;
|
||||
|
||||
public final class Region extends AbstractRegion {
|
||||
|
||||
@@ -39,15 +40,19 @@ public final class Region extends AbstractRegion {
|
||||
@Override
|
||||
public String baseString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(blocks.size());
|
||||
for (IContainer cont : blocks) {
|
||||
sb.append(cont.baseString());
|
||||
int size = blocks.size();
|
||||
sb.append('(');
|
||||
sb.append(size);
|
||||
if (size > 0) {
|
||||
sb.append(':');
|
||||
Utils.listToString(sb, blocks, "|", IContainer::baseString);
|
||||
}
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "R:" + baseString();
|
||||
return "R" + baseString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,11 +142,10 @@ public final class IfCondition {
|
||||
Compare c = cond.getCompare();
|
||||
simplifyCmpOp(c);
|
||||
if (c.getOp() == IfOp.EQ && c.getB().isLiteral() && c.getB().equals(LiteralArg.FALSE)) {
|
||||
return not(new IfCondition(c.invert()));
|
||||
cond = not(new IfCondition(c.invert()));
|
||||
} else {
|
||||
c.normalize();
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
List<IfCondition> args = null;
|
||||
for (int i = 0; i < cond.getArgs().size(); i++) {
|
||||
@@ -225,7 +224,7 @@ public final class IfCondition {
|
||||
case TERNARY:
|
||||
return first() + " ? " + second() + " : " + third();
|
||||
case NOT:
|
||||
return "!" + first();
|
||||
return "!(" + first() + ")";
|
||||
case AND:
|
||||
case OR:
|
||||
String op = mode == Mode.OR ? " || " : " && ";
|
||||
|
||||
@@ -79,7 +79,6 @@ public class BlockProcessor extends AbstractVisitor {
|
||||
|
||||
private static boolean removeEmptyBlock(BlockNode block) {
|
||||
if (canRemoveBlock(block)) {
|
||||
LOG.debug("Removing empty block: {}", block);
|
||||
if (block.getSuccessors().size() == 1) {
|
||||
BlockNode successor = block.getSuccessors().get(0);
|
||||
block.getPredecessors().forEach(pred -> {
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.EdgeInsnAttr;
|
||||
@@ -43,7 +42,6 @@ import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.ErrorsCounter;
|
||||
import jadx.core.utils.InstructionRemover;
|
||||
import jadx.core.utils.RegionUtils;
|
||||
import jadx.core.utils.exceptions.JadxOverflowException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.dex.visitors.regions.IfMakerHelper.confirmMerge;
|
||||
@@ -62,12 +60,20 @@ public class RegionMaker {
|
||||
|
||||
private final MethodNode mth;
|
||||
private int regionsCount;
|
||||
private Region[] regionByBlock;
|
||||
|
||||
public RegionMaker(MethodNode mth) {
|
||||
this.mth = mth;
|
||||
this.regionByBlock = new Region[mth.getBasicBlocks().size()];
|
||||
}
|
||||
|
||||
public Region makeRegion(BlockNode startBlock, RegionStack stack) {
|
||||
int startBlockId = startBlock.getId();
|
||||
Region region = regionByBlock[startBlockId];
|
||||
if (region != null) {
|
||||
return region;
|
||||
}
|
||||
|
||||
Region r = new Region(stack.peekRegion());
|
||||
BlockNode next = startBlock;
|
||||
while (next != null) {
|
||||
@@ -77,6 +83,7 @@ public class RegionMaker {
|
||||
throw new JadxRuntimeException("Regions count limit reached");
|
||||
}
|
||||
}
|
||||
regionByBlock[startBlockId] = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,9 +79,7 @@ public class BlockUtils {
|
||||
}
|
||||
if (b.contains(AFlag.SYNTHETIC)) {
|
||||
List<BlockNode> s = b.getSuccessors();
|
||||
if (s.size() == 1 && s.get(0).contains(AType.EXC_HANDLER)) {
|
||||
return true;
|
||||
}
|
||||
return s.size() == 1 && s.get(0).contains(AType.EXC_HANDLER);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -156,7 +154,10 @@ public class BlockUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static InsnNode getLastInsn(IBlock block) {
|
||||
public static InsnNode getLastInsn(@Nullable IBlock block) {
|
||||
if (block == null) {
|
||||
return null;
|
||||
}
|
||||
List<InsnNode> insns = block.getInstructions();
|
||||
if (insns.isEmpty()) {
|
||||
return null;
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jadx.api.JadxDecompiler;
|
||||
|
||||
@@ -26,19 +27,30 @@ public class Utils {
|
||||
return 'L' + obj.replace('.', '/') + ';';
|
||||
}
|
||||
|
||||
public static String listToString(Iterable<?> list) {
|
||||
if (list == null) {
|
||||
public static String listToString(Iterable<?> objects) {
|
||||
return listToString(objects, ", ");
|
||||
}
|
||||
|
||||
public static String listToString(Iterable<?> objects, String joiner) {
|
||||
if (objects == null) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder str = new StringBuilder();
|
||||
for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
|
||||
Object o = it.next();
|
||||
str.append(o);
|
||||
if (it.hasNext()) {
|
||||
str.append(", ");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
listToString(sb, objects, joiner, Object::toString);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static <T> void listToString(StringBuilder sb, Iterable<T> objects, String joiner, Function<T, String> toStr) {
|
||||
if (objects == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<T> it = objects.iterator();
|
||||
if (it.hasNext()) {
|
||||
sb.append(toStr.apply(it.next()));
|
||||
}
|
||||
while (it.hasNext()) {
|
||||
sb.append(joiner).append(toStr.apply(it.next()));
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public static String arrayToString(Object[] array) {
|
||||
|
||||
Reference in New Issue
Block a user