未验证 提交 49d0e762 编写于 作者: S Skylot

fix: support all-catch in multi-catch (#1510)

上级 0809993b
......@@ -14,9 +14,9 @@ import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
public class ExceptionHandler {
......@@ -33,9 +33,14 @@ public class ExceptionHandler {
private boolean removed = false;
public ExceptionHandler(int addr, @Nullable ClassInfo type) {
public static ExceptionHandler build(MethodNode mth, int addr, @Nullable ClassInfo type) {
ExceptionHandler eh = new ExceptionHandler(addr);
eh.addCatchType(mth, type);
return eh;
}
private ExceptionHandler(int addr) {
this.handlerOffset = addr;
addCatchType(type);
}
/**
......@@ -43,7 +48,7 @@ public class ExceptionHandler {
*
* @param type - null for 'all' or 'Throwable' handler
*/
public boolean addCatchType(@Nullable ClassInfo type) {
public boolean addCatchType(MethodNode mth, @Nullable ClassInfo type) {
if (type != null) {
if (catchTypes.contains(type)) {
return false;
......@@ -51,14 +56,16 @@ public class ExceptionHandler {
return catchTypes.add(type);
}
if (!this.catchTypes.isEmpty()) {
throw new JadxRuntimeException("Null type added to not empty exception handler: " + this);
mth.addDebugComment("Throwable added to exception handler: '" + catchTypeStr() + "', keep only Throwable");
catchTypes.clear();
return true;
}
return false;
}
public void addCatchTypes(Collection<ClassInfo> types) {
public void addCatchTypes(MethodNode mth, Collection<ClassInfo> types) {
for (ClassInfo type : types) {
addCatchType(type);
addCatchType(mth, type);
}
}
......
......@@ -133,7 +133,7 @@ public class AttachTryCatchVisitor extends AbstractVisitor {
ExcHandlerAttr excHandlerAttr = insn.get(AType.EXC_HANDLER);
if (excHandlerAttr != null) {
ExceptionHandler handler = excHandlerAttr.getHandler();
if (handler.addCatchType(type)) {
if (handler.addCatchType(mth, type)) {
// exist handler updated (assume from same try block) - don't add again
return null;
}
......@@ -143,7 +143,7 @@ public class AttachTryCatchVisitor extends AbstractVisitor {
} else {
insn = insertNOP(insnByOffset, handlerOffset);
}
ExceptionHandler handler = new ExceptionHandler(handlerOffset, type);
ExceptionHandler handler = ExceptionHandler.build(mth, handlerOffset, type);
mth.addExceptionHandler(handler);
insn.addAttr(new ExcHandlerAttr(handler));
return handler;
......
......@@ -549,7 +549,7 @@ public class BlockExceptionHandler {
if (handler == resultHandler) {
return false;
}
resultHandler.addCatchTypes(handler.getCatchTypes());
resultHandler.addCatchTypes(mth, handler.getCatchTypes());
handler.markForRemove();
return true;
});
......
......@@ -25,8 +25,6 @@ public class TestTryCatchMultiException extends IntegrationTest {
@Test
public void test() {
// printDisassemble();
// setFallback();
noDebugInfo();
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
......
package jadx.tests.integration.trycatch;
import org.junit.jupiter.api.Test;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
@SuppressWarnings("CommentedOutCode")
public class TestTryCatchMultiException2 extends SmaliTest {
// @formatter:off
/*
public static boolean test() {
try {
Class<?> cls = Class.forName("c");
return ((Boolean) cls.getMethod("b", new Class[0]).invoke(cls, new Object[0])).booleanValue();
} catch (ClassNotFoundException | NoSuchMethodException | Exception | Throwable unused) {
// java compiler don't allow shadow subclasses in multi-catch
// in this case leave only Throwable
return false;
}
}
*/
// @formatter:on
@Test
public void test() {
assertThat(getClassNodeFromSmali())
.code()
.containsOne("} catch (Throwable unused) {");
}
}
.class public Ltrycatch/TestTryCatchMultiException2;
.super Ljava/lang/Object;
.method public static test()Z
.registers 5
:try_start_b
const-string v0, "c"
invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
move-result-object v1
const/4 v0, 0x0
const-string v2, "b"
new-array v3, v0, [Ljava/lang/Class;
invoke-virtual {v1, v2, v3}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
move-result-object v2
new-array v3, v0, [Ljava/lang/Object;
invoke-virtual {v2, v1, v3}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Ljava/lang/Boolean;
invoke-virtual {v1}, Ljava/lang/Boolean;->booleanValue()Z
move-result v1
:try_end_2f
.catch Ljava/lang/ClassNotFoundException; {:try_start_b .. :try_end_2f} :catch_30
.catch Ljava/lang/NoSuchMethodException; {:try_start_b .. :try_end_2f} :catch_30
.catch Ljava/lang/Exception; {:try_start_b .. :try_end_2f} :catch_30
.catchall {:try_start_b .. :try_end_2f} :catchall_30
return v1
:catch_30
:catchall_30
return v0
.end method
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册