Commit 17d8516d authored by Skylot's avatar Skylot

fix: made correct instructions remove in new filled array replacement (#461)

parent b78349ae
......@@ -10,7 +10,6 @@ println("jadx version: ${jadxVersion}")
allprojects {
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'jacoco'
version = jadxVersion
......
......@@ -495,7 +495,7 @@ public class InsnGen {
case NEW_INSTANCE:
// only fallback - make new instance in constructor invoke
fallbackOnlyInsn(insn);
code.add("new ").add(insn.getResult().getType().toString());
code.add("new ").add(insn.getResult().getInitType().toString());
break;
case PHI:
......
......@@ -11,7 +11,7 @@ import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -64,7 +64,7 @@ public final class PhiInsn extends InsnNode {
if (super.removeArg(reg)) {
blockBinds.remove(reg);
reg.getSVar().removeUse(reg);
InstructionRemover.fixUsedInPhiFlag(reg);
InsnRemover.fixUsedInPhiFlag(reg);
return true;
}
return false;
......
......@@ -19,8 +19,8 @@ import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.Utils;
public class InsnNode extends LineAttrNode {
......@@ -68,6 +68,15 @@ public class InsnNode extends LineAttrNode {
public void addArg(InsnArg arg) {
arguments.add(arg);
attachArg(arg);
}
public void setArg(int n, InsnArg arg) {
arguments.set(n, arg);
attachArg(arg);
}
private void attachArg(InsnArg arg) {
arg.setParentInsn(this);
if (arg.isRegister()) {
RegisterArg reg = (RegisterArg) arg;
......@@ -108,22 +117,15 @@ public class InsnNode extends LineAttrNode {
return false;
}
public void setArg(int n, InsnArg arg) {
arg.setParentInsn(this);
arguments.set(n, arg);
}
/**
* Replace instruction arg with another using recursive search.
* <br>
* <b>Caution:</b> this method don't change usage information for replaced argument.
*/
public boolean replaceArg(InsnArg from, InsnArg to) {
int count = getArgsCount();
for (int i = 0; i < count; i++) {
InsnArg arg = arguments.get(i);
if (arg == from) {
InstructionRemover.unbindArgUsage(null, arg);
InsnRemover.unbindArgUsage(null, arg);
setArg(i, to);
return true;
}
......@@ -139,7 +141,7 @@ public class InsnNode extends LineAttrNode {
for (int i = 0; i < count; i++) {
if (arg == arguments.get(i)) {
arguments.remove(i);
InstructionRemover.unbindArgUsage(null, arg);
InsnRemover.unbindArgUsage(null, arg);
return true;
}
}
......
......@@ -29,7 +29,7 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException;
@JadxVisitor(
......@@ -131,7 +131,7 @@ public class ClassModifier extends AbstractVisitor {
return false;
}
mth.skipFirstArgument();
InstructionRemover.remove(mth, block, insn);
InsnRemover.remove(mth, block, insn);
// other arg usage -> wrap with IGET insn
if (arg.getSVar().getUseCount() != 0) {
InsnNode iget = new IndexInsnNode(InsnType.IGET, fieldInfo, 1);
......
......@@ -20,7 +20,7 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxOverflowException;
......@@ -46,7 +46,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
for (InsnNode insn : block.getInstructions()) {
checkInsn(mth, insn, toRemove);
}
InstructionRemover.removeAll(mth, block, toRemove);
InsnRemover.removeAllAndUnbind(mth, block, toRemove);
}
}
......
......@@ -17,7 +17,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
@JadxVisitor(
name = "ConstructorVisitor",
......@@ -36,7 +36,7 @@ public class ConstructorVisitor extends AbstractVisitor {
}
private static void replaceInvoke(MethodNode mth) {
InstructionRemover remover = new InstructionRemover(mth);
InsnRemover remover = new InsnRemover(mth);
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
int size = block.getInstructions().size();
......@@ -50,7 +50,7 @@ public class ConstructorVisitor extends AbstractVisitor {
}
}
private static void processInvoke(MethodNode mth, BlockNode block, int indexInBlock, InstructionRemover remover) {
private static void processInvoke(MethodNode mth, BlockNode block, int indexInBlock, InsnRemover remover) {
ClassNode parentClass = mth.getParentClass();
InsnNode insn = block.getInstructions().get(indexInBlock);
InvokeNode inv = (InvokeNode) insn;
......@@ -75,25 +75,24 @@ public class ConstructorVisitor extends AbstractVisitor {
remove = true;
}
if (remove) {
remover.add(insn);
remover.addAndUnbind(insn);
return;
}
if (co.isNewInstance()) {
InsnNode newInstInsn = removeAssignChain(mth, instArgAssignInsn, remover, InsnType.NEW_INSTANCE);
if (newInstInsn != null) {
remover.addWithoutUnbind(newInstInsn);
RegisterArg instArg = newInstInsn.getResult();
RegisterArg resultArg = co.getResult();
if (!resultArg.equals(instArg)) {
// replace all usages of 'instArg' with result of this constructor instruction
for (RegisterArg useArg : new ArrayList<>(instArg.getSVar().getUseList())) {
RegisterArg dup = resultArg.duplicate();
InsnNode parentInsn = useArg.getParentInsn();
parentInsn.replaceArg(useArg, dup);
dup.setParentInsn(parentInsn);
resultArg.getSVar().use(dup);
if (parentInsn != null) {
parentInsn.replaceArg(useArg, resultArg.duplicate());
}
}
}
newInstInsn.setResult(null); // don't unbind result arg on remove
}
}
ConstructorInsn replace = processConstructor(mth, co);
......@@ -146,19 +145,19 @@ public class ConstructorVisitor extends AbstractVisitor {
/**
* Remove instructions on 'move' chain until instruction with type 'insnType'
*/
private static InsnNode removeAssignChain(MethodNode mth, InsnNode insn, InstructionRemover remover, InsnType insnType) {
private static InsnNode removeAssignChain(MethodNode mth, InsnNode insn, InsnRemover remover, InsnType insnType) {
if (insn == null) {
return null;
}
if (insn.isAttrStorageEmpty()) {
remover.add(insn);
} else {
BlockUtils.replaceInsn(mth, insn, new InsnNode(InsnType.NOP, 0));
}
InsnType type = insn.getType();
if (type == insnType) {
return insn;
}
if (insn.isAttrStorageEmpty()) {
remover.addWithoutUnbind(insn);
} else {
BlockUtils.replaceInsn(mth, insn, new InsnNode(InsnType.NOP, 0));
}
if (type == InsnType.MOVE) {
RegisterArg arg = (RegisterArg) insn.getArg(0);
return removeAssignChain(mth, arg.getAssignInsn(), remover, insnType);
......
......@@ -22,7 +22,7 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.parser.FieldInitAttr;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException;
@JadxVisitor(
......@@ -92,7 +92,7 @@ public class ExtractFieldInit extends AbstractVisitor {
if (initInsns.size() == 1) {
InsnNode insn = initInsns.get(0);
if (checkInsn(insn)) {
InstructionRemover.remove(classInitMth, insn);
InsnRemover.remove(classInitMth, insn);
addFieldInitAttr(classInitMth, field, insn);
}
}
......@@ -165,7 +165,7 @@ public class ExtractFieldInit extends AbstractVisitor {
// all checks passed
for (InitInfo info : infoList) {
for (InsnNode putInsn : info.getPutInsns()) {
InstructionRemover.remove(info.getConstrMth(), putInsn);
InsnRemover.remove(info.getConstrMth(), putInsn);
}
}
for (InsnNode insn : common.getPutInsns()) {
......
......@@ -40,7 +40,7 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.utils.BlockUtils.replaceInsn;
......@@ -63,12 +63,12 @@ public class ModVisitor extends AbstractVisitor {
return;
}
InstructionRemover remover = new InstructionRemover(mth);
InsnRemover remover = new InsnRemover(mth);
replaceStep(mth, remover);
removeStep(mth, remover);
}
private static void replaceStep(MethodNode mth, InstructionRemover remover) {
private static void replaceStep(MethodNode mth, InsnRemover remover) {
ClassNode parentClass = mth.getParentClass();
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
......@@ -120,7 +120,7 @@ public class ModVisitor extends AbstractVisitor {
InsnNode filledArr = makeFilledArrayInsn(mth, (NewArrayNode) insn, (FillArrayNode) ni);
if (filledArr != null) {
replaceInsn(block, i, filledArr);
remover.add(ni);
remover.addAndUnbind(ni);
}
}
}
......@@ -182,7 +182,7 @@ public class ModVisitor extends AbstractVisitor {
/**
* Remove unnecessary instructions
*/
private static void removeStep(MethodNode mth, InstructionRemover remover) {
private static void removeStep(MethodNode mth, InsnRemover remover) {
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
for (InsnNode insn : block.getInstructions()) {
......@@ -190,7 +190,7 @@ public class ModVisitor extends AbstractVisitor {
case NOP:
case GOTO:
case NEW_INSTANCE:
remover.add(insn);
remover.addAndUnbind(insn);
break;
default:
......@@ -335,7 +335,7 @@ public class ModVisitor extends AbstractVisitor {
return filledArr;
}
private static void processMoveException(BlockNode block, InsnNode insn, InstructionRemover remover) {
private static void processMoveException(BlockNode block, InsnNode insn, InsnRemover remover) {
ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) {
return;
......@@ -352,7 +352,7 @@ public class ModVisitor extends AbstractVisitor {
SSAVar sVar = insn.getResult().getSVar();
if (sVar.getUseCount() == 0) {
excHandler.setArg(new NamedArg(name, type));
remover.add(insn);
remover.addAndUnbind(insn);
} else if (sVar.isUsedInPhi()) {
// exception var moved to external variable => replace with 'move' insn
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
......
......@@ -33,7 +33,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.utils.InsnList;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxException;
......@@ -57,7 +57,7 @@ public class ReSugarCode extends AbstractVisitor {
if (mth.isNoCode()) {
return;
}
InstructionRemover remover = new InstructionRemover(mth);
InsnRemover remover = new InsnRemover(mth);
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
List<InsnNode> instructions = block.getInstructions();
......@@ -69,14 +69,14 @@ public class ReSugarCode extends AbstractVisitor {
}
}
private static void process(MethodNode mth, List<InsnNode> instructions, int i, InstructionRemover remover) {
private static void process(MethodNode mth, List<InsnNode> instructions, int i, InsnRemover remover) {
InsnNode insn = instructions.get(i);
if (insn.contains(AFlag.REMOVE)) {
return;
}
switch (insn.getType()) {
case NEW_ARRAY:
processNewArray(mth, instructions, i, remover);
processNewArray(mth, (NewArrayNode) insn, instructions, remover);
break;
case SWITCH:
......@@ -91,9 +91,8 @@ public class ReSugarCode extends AbstractVisitor {
/**
* Replace new array and sequence of array-put to new filled-array instruction.
*/
private static void processNewArray(MethodNode mth, List<InsnNode> instructions, int i,
InstructionRemover remover) {
NewArrayNode newArrayInsn = (NewArrayNode) instructions.get(i);
private static void processNewArray(MethodNode mth, NewArrayNode newArrayInsn,
List<InsnNode> instructions, InsnRemover remover) {
InsnArg arrLenArg = newArrayInsn.getArg(0);
if (!arrLenArg.isLiteral()) {
return;
......@@ -136,12 +135,13 @@ public class ReSugarCode extends AbstractVisitor {
// checks complete, apply
ArgType arrType = newArrayInsn.getArrayType();
InsnNode filledArr = new FilledNewArrayNode(arrType.getArrayElement(), len);
filledArr.setResult(arrArg.duplicate());
filledArr.setResult(arrArg);
for (InsnNode put : arrPuts) {
filledArr.addArg(put.getArg(2).duplicate());
remover.addAndUnbind(mth, put);
filledArr.addArg(put.getArg(2));
remover.addWithoutUnbind(put);
InsnRemover.unbindArgUsage(mth, put.getArg(0));
}
remover.addAndUnbind(mth, newArrayInsn);
remover.addWithoutUnbind(newArrayInsn);
int replaceIndex = InsnList.getIndex(instructions, Utils.last(arrPuts));
instructions.set(replaceIndex, filledArr);
......
......@@ -16,7 +16,7 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
public class BlockExceptionHandler extends AbstractVisitor {
......@@ -77,13 +77,13 @@ public class BlockExceptionHandler extends AbstractVisitor {
}
for (BlockNode excBlock : excHandler.getBlocks()) {
// remove 'monitor-exit' from exception handler blocks
InstructionRemover remover = new InstructionRemover(mth, excBlock);
InsnRemover remover = new InsnRemover(mth, excBlock);
for (InsnNode insn : excBlock.getInstructions()) {
if (insn.getType() == InsnType.MONITOR_ENTER) {
break;
}
if (insn.getType() == InsnType.MONITOR_EXIT) {
remover.add(insn);
remover.addAndUnbind(insn);
}
}
remover.perform();
......
......@@ -41,7 +41,7 @@ import jadx.core.dex.trycatch.SplitterBlockAttr;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -567,7 +567,7 @@ public class RegionMaker {
}
exitInsn.add(AFlag.DONT_GENERATE);
exitInsn.add(AFlag.REMOVE);
InstructionRemover.unbindInsn(mth, exitInsn);
InsnRemover.unbindInsn(mth, exitInsn);
}
BlockNode body = getNextBlock(block);
......
......@@ -25,7 +25,7 @@ import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxException;
......@@ -176,10 +176,10 @@ public class RegionMakerVisitor extends AbstractVisitor {
// replace synchronized block with inner region
startRegion.getSubBlocks().set(0, synchRegion.getRegion());
// remove 'monitor-enter' instruction
InstructionRemover.remove(mth, synchInsn);
InsnRemover.remove(mth, synchInsn);
// remove 'monitor-exit' instruction
for (InsnNode exit : synchRegion.getExitInsns()) {
InstructionRemover.remove(mth, exit);
InsnRemover.remove(mth, exit);
}
// run region cleaner again
CleanRegions.process(mth);
......
......@@ -28,6 +28,7 @@ import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.regions.DepthRegionTraversal;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxException;
public class ProcessVariables extends AbstractVisitor {
......@@ -148,9 +149,7 @@ public class ProcessVariables extends AbstractVisitor {
list.add(usage);
}
}
if (!list.isEmpty()) {
codeVarUsage.put(codeVar, list);
}
codeVarUsage.put(codeVar, Utils.lockList(list));
}
return codeVarUsage;
}
......
......@@ -22,7 +22,7 @@ import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.JadxVisitor;
import jadx.core.dex.visitors.blocksmaker.BlockFinish;
import jadx.core.utils.InsnList;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -235,7 +235,7 @@ public class SSATransform extends AbstractVisitor {
InsnNode parentInsn = arg.getAssignInsn();
if (parentInsn != null && parentInsn.contains(AFlag.REMOVE)) {
phi.removeArg(arg);
InstructionRemover.remove(mth, block, parentInsn);
InsnRemover.remove(mth, block, parentInsn);
removed = true;
}
}
......@@ -283,7 +283,7 @@ public class SSATransform extends AbstractVisitor {
phi.removeArg(useArg);
}
}
InstructionRemover.remove(mth, block, phi);
InsnRemover.remove(mth, block, phi);
return true;
}
boolean allSame = phi.getArgsCount() == 1 || isSameArgs(phi);
......@@ -326,7 +326,7 @@ public class SSATransform extends AbstractVisitor {
sVar.setUsedInPhi(null);
}
}
InstructionRemover.remove(mth, block, phiInsn);
InsnRemover.remove(mth, block, phiInsn);
}
}
if (list.isEmpty()) {
......@@ -396,7 +396,7 @@ public class SSATransform extends AbstractVisitor {
assignInsn.add(AFlag.DONT_INLINE);
}
}
InstructionRemover.unbindInsn(mth, phi);
InsnRemover.unbindInsn(mth, phi);
return true;
}
......
......@@ -19,17 +19,17 @@ import jadx.core.dex.nodes.MethodNode;
* Helper class for correct instructions removing,
* can be used while iterating over instructions list
*/
public class InstructionRemover {
public class InsnRemover {
private final MethodNode mth;
private final List<InsnNode> toRemove;
private List<InsnNode> instrList;
public InstructionRemover(MethodNode mth) {
public InsnRemover(MethodNode mth) {
this(mth, null);
}
public InstructionRemover(MethodNode mth, BlockNode block) {
public InsnRemover(MethodNode mth, BlockNode block) {
this.mth = mth;
this.toRemove = new ArrayList<>();
if (block != null) {
......@@ -41,20 +41,20 @@ public class InstructionRemover {
this.instrList = block.getInstructions();
}
public void add(InsnNode insn) {
public void addAndUnbind(InsnNode insn) {
toRemove.add(insn);
unbindInsn(mth, insn);
}
public void addAndUnbind(MethodNode mth, InsnNode insn) {
public void addWithoutUnbind(InsnNode insn) {
toRemove.add(insn);
unbindInsn(mth, insn);
}
public void perform() {
if (toRemove.isEmpty()) {
return;
}
removeAll(mth, instrList, toRemove);
removeAll(instrList, toRemove);
toRemove.clear();
}
......@@ -111,7 +111,7 @@ public class InstructionRemover {
// Don't use 'instrList.removeAll(toRemove)' because it will remove instructions by content
// and here can be several instructions with same content
private static void removeAll(MethodNode mth, List<InsnNode> insns, List<InsnNode> toRemove) {
private static void removeAll(List<InsnNode> insns, List<InsnNode> toRemove) {
if (toRemove == null || toRemove.isEmpty()) {
return;
}
......@@ -120,7 +120,6 @@ public class InstructionRemover {
for (int i = 0; i < insnsCount; i++) {
if (insns.get(i) == rem) {
insns.remove(i);
unbindInsn(mth, rem);
break;
}
}
......@@ -147,8 +146,11 @@ public class InstructionRemover {
}
}
public static void removeAll(MethodNode mth, BlockNode block, List<InsnNode> insns) {
removeAll(mth, block.getInstructions(), insns);
public static void removeAllAndUnbind(MethodNode mth, BlockNode block, List<InsnNode> insns) {
for (InsnNode insn : insns) {
unbindInsn(mth, insn);
}
removeAll(block.getInstructions(), insns);
}
public static void remove(MethodNode mth, BlockNode block, int index) {
......
package jadx.tests.integration.inline;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
public class TestInline7 extends SmaliTest {
/*
public void onViewCreated(View view, @Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
view.findViewById(R.id.done_button_early_release_failure).setOnClickListener(new SafeClickListener(this));
Bundle arguments = getArguments();
if (arguments != null) {
((TextView) view.findViewById(R.id.summary_content_early_release_failure)).setText(
getString(R.string.withdraw_id_capture_failure_content,
new Object[]{arguments.getString("withdrawAmount"), arguments.getString ("withdrawHoldTime")})
);
}
}
*/
@Test
public void test() {
disableCompilation();
ClassNode cls = getClassNodeFromSmaliWithPkg("inline", "TestInline7");
String code = cls.getCode().toString();
assertThat(code, not(containsString("Bundle arguments;")));
assertThat(code, containsOne("Bundle arguments = getArguments();"));
assertThat(code, containsOne("@Nullable Bundle bundle"));
}
}
......@@ -2,36 +2,48 @@ package jadx.tests.integration.invoke;
import org.junit.jupiter.api.Test;
import jadx.NotYetImplemented;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
public class TestConstructorInvoke extends IntegrationTest {
public class TestCls {
void test(String root, String name) {
ViewHolder viewHolder = new ViewHolder(root, name);
}
private final class ViewHolder {
private int mElements = 0;
private final String mRoot;
private String mName;
void test(String root, String name) {
ViewHolder holder = new ViewHolder(root, name);
}
private ViewHolder(String root, String name) {
this.mRoot = root;
this.mName = name;
}
private final class ViewHolder {
private ViewHolder(String root, String name) {
}
}
@Test
@NotYetImplemented("Variable lost name from debug info")
public void test() {
ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString();
assertThat(code, containsString("new ViewHolder(root, name);"));
assertThat(code, containsOne(indent() + "ViewHolder holder = new ViewHolder(root, name);"));
}
// Remove after fix above @NYI
@Test
public void test2() {
ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString();
assertThat(code, containsOne(indent() + "ViewHolder viewHolder = new ViewHolder(root, name);"));
}
@Test
public void testNoDebug() {
noDebugInfo();
ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString();
assertThat(code, containsOne(indent() + "ViewHolder viewHolder = new ViewHolder("));
}
}
......@@ -13,7 +13,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.InsnRemover;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
......@@ -33,13 +33,13 @@ public class TestContinueInLoop2 extends IntegrationTest {
excHandler.addBlock(node);
}
for (BlockNode excBlock : excHandler.getBlocks()) {
InstructionRemover remover = new InstructionRemover(mth, excBlock);
InsnRemover remover = new InsnRemover(mth, excBlock);
for (InsnNode insn : excBlock.getInstructions()) {
if (insn.getType() == InsnType.MONITOR_ENTER) {
break;
}
if (insn.getType() == InsnType.MONITOR_EXIT) {
remover.add(insn);
remover.addAndUnbind(insn);
}
}
remover.perform();
......
.class public Linline/TestInline7;
.super Ljava/lang/Object;
.method public onViewCreated(Landroid/view/View;Landroid/os/Bundle;)V
.locals 4
.param p2 # Landroid/os/Bundle;
.annotation build Landroid/support/annotation/Nullable;
.end annotation
.end param
.line 42
invoke-super {p0, p1, p2}, Lapp/navigation/fragment/NodeFragment;->onViewCreated(Landroid/view/View;Landroid/os/Bundle;)V
.line 43
sget p2, Lapp/wallet/R$id;->done_button_early_release_failure:I
invoke-virtual {p1, p2}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object p2
new-instance v0, Lapp/common/utils/SafeClickListener;
invoke-direct {v0, p0}, Lapp/common/utils/SafeClickListener;-><init>(Lapp/common/utils/ISafeClickVerifierListener;)V
invoke-virtual {p2, v0}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V
.line 44
invoke-virtual {p0}, Linline/TestInline7;->getArguments()Landroid/os/Bundle;
move-result-object p2
if-eqz p2, :cond_0
.line 46
sget v0, Lapp/wallet/R$id;->summary_content_early_release_failure:I
invoke-virtual {p1, v0}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object p1
check-cast p1, Landroid/widget/TextView;
sget v0, Lapp/wallet/R$string;->withdraw_id_capture_failure_content:I
const/4 v1, 0x2
new-array v1, v1, [Ljava/lang/Object;
const/4 v2, 0x0
const-string v3, "withdrawAmount"
invoke-virtual {p2, v3}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
move-result-object v3
aput-object v3, v1, v2
const/4 v2, 0x1
const-string v3, "withdrawHoldTime"
invoke-virtual {p2, v3}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
move-result-object p2
aput-object p2, v1, v2
invoke-virtual {p0, v0, v1}, Linline/TestInline7;->getString(I[Ljava/lang/Object;)Ljava/lang/String;
move-result-object p2
invoke-virtual {p1, p2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
:cond_0
return-void
.end method
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment