fix: additional checks for primitive deboxing (#1838)

This commit is contained in:
Skylot
2023-04-24 20:35:11 +01:00
parent ea10f2af47
commit 7f3bd8c668
2 changed files with 58 additions and 2 deletions
@@ -99,7 +99,7 @@ public class DeboxingVisitor extends AbstractVisitor {
}
arg.setType(primitiveType);
boolean forbidInline;
if (canChangeTypeToPrimitive(resArg)) {
if (canChangeTypeToPrimitive(resArg, boxType)) {
resArg.setType(primitiveType);
forbidInline = false;
} else {
@@ -132,7 +132,7 @@ public class DeboxingVisitor extends AbstractVisitor {
return false;
}
private boolean canChangeTypeToPrimitive(RegisterArg arg) {
private boolean canChangeTypeToPrimitive(RegisterArg arg, ArgType boxType) {
for (SSAVar ssaVar : arg.getSVar().getCodeVar().getSsaVars()) {
if (ssaVar.isTypeImmutable()) {
return false;
@@ -148,6 +148,12 @@ public class DeboxingVisitor extends AbstractVisitor {
return false;
}
}
ArgType initType = assignInsn.getResult().getInitType();
if (initType.isObject() && !initType.equals(boxType)) {
// some of related vars have another object type
return false;
}
for (RegisterArg useArg : ssaVar.getUseList()) {
InsnNode parentInsn = useArg.getParentInsn();
if (parentInsn == null) {
@@ -0,0 +1,50 @@
package jadx.tests.integration.others;
import jadx.tests.api.IntegrationTest;
import jadx.tests.api.extensions.profiles.TestProfile;
import jadx.tests.api.extensions.profiles.TestWithProfiles;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
public class TestDeboxing5 extends IntegrationTest {
@SuppressWarnings("WrapperTypeMayBePrimitive")
public static class TestCls {
private static String type;
public static void test(String[] args) {
Float f = (float) -47.99;
Boolean b = args.length == 0;
Object o = ((b) ? false : f);
call(o);
}
public static void call(Object o) {
if (o instanceof Boolean) {
type = "Boolean";
}
if (o instanceof Float) {
type = "Float";
}
}
private static void verify(String[] arr, String str) {
type = null;
test(arr);
assertThat(type).isEqualTo(str);
}
public void check() {
verify(new String[0], "Boolean");
verify(new String[] { "1" }, "Float");
}
}
@TestWithProfiles(TestProfile.D8_J11)
public void test() {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("boolean valueOf");
}
}