diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index e380fe2a26de48163124c2135f34dc73a2e89357..a1cbd82d34db023551103e29fd4d98147b0b9459 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -370,7 +370,7 @@ public class ClassGen { if (fv != null) { code.add(" = "); if (fv.getValue() == null) { - code.add(TypeGen.literalToString(0, f.getType(), cls)); + code.add(TypeGen.literalToString(0, f.getType(), cls, fallback)); } else { if (fv.getValueType() == InitType.CONST) { annotationGen.encodeValue(code, fv.getValue()); diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 9311c911c884f02c955dcf9dce8104c2245041be..377eb38d0269b5fcbfc6cf719ad521991201c983 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -138,7 +138,7 @@ public class InsnGen { } private String lit(LiteralArg arg) { - return TypeGen.literalToString(arg.getLiteral(), arg.getType(), mth); + return TypeGen.literalToString(arg.getLiteral(), arg.getType(), mth, fallback); } private void instanceField(CodeWriter code, FieldInfo field, InsnArg arg) throws CodegenException { diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index f9a14c5b88b978f00176ab560a45eaf58a42610d..a4e0ba0525c9246bfabb00cd386e755ef425af03 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -148,7 +148,13 @@ public class MethodGen { if (var.isFinal()) { code.add("final "); } - ArgType argType = var.getType(); + ArgType argType; + if (var.getType() == ArgType.UNKNOWN) { + // occur on decompilation errors + argType = mthArg.getInitType(); + } else { + argType = var.getType(); + } if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) { // change last array argument to varargs if (argType.isArray()) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index ca797c01e74418a4d4aedd2d14bf20437b55f966..28b72c61f91662a342e578676f87c54bb412d07c 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -266,7 +266,7 @@ public class RegionGen extends InsnGen { } } } else if (k instanceof Integer) { - code.add(TypeGen.literalToString((Integer) k, arg.getType(), mth)); + code.add(TypeGen.literalToString((Integer) k, arg.getType(), mth, fallback)); } else { throw new JadxRuntimeException("Unexpected key in switch: " + (k != null ? k.getClass() : null)); } diff --git a/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java b/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java index e241549502de02e0cce07a373a9a8934d1d53bda..2156ba8f940fe31442300532f94baad02e466157 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java @@ -33,14 +33,14 @@ public class TypeGen { * * @throws JadxRuntimeException for incorrect type or literal value */ - public static String literalToString(long lit, ArgType type, IDexNode dexNode) { - return literalToString(lit, type, dexNode.root().getStringUtils()); + public static String literalToString(long lit, ArgType type, IDexNode dexNode, boolean fallback) { + return literalToString(lit, type, dexNode.root().getStringUtils(), fallback); } - public static String literalToString(long lit, ArgType type, StringUtils stringUtils) { + public static String literalToString(long lit, ArgType type, StringUtils stringUtils, boolean fallback) { if (type == null || !type.isTypeKnown()) { String n = Long.toString(lit); - if (Math.abs(lit) > 100) { + if (fallback && Math.abs(lit) > 100) { StringBuilder sb = new StringBuilder(); sb.append(n).append("(0x").append(Long.toHexString(lit)); if (type == null || type.contains(PrimitiveType.FLOAT)) { diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java index 4e5740a691d851003dc5669bfe1a1feff97c9565..156b7582fb1456d7de117f4cf521b1cb53ed0a3d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java @@ -70,7 +70,7 @@ public final class LiteralArg extends InsnArg { @Override public String toString() { try { - String value = TypeGen.literalToString(literal, getType(), DEF_STRING_UTILS); + String value = TypeGen.literalToString(literal, getType(), DEF_STRING_UTILS, true); if (getType().equals(ArgType.BOOLEAN) && (value.equals("true") || value.equals("false"))) { return value; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java index d1f9b521b431d98986fead5624698a6f9bf63489..f6cb41890f248d4a51775efe0492ded70dffb8c9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java @@ -5,11 +5,15 @@ import java.util.List; import org.jetbrains.annotations.Nullable; +import com.android.dx.rop.code.AccessFlags; + import jadx.core.codegen.TypeGen; import jadx.core.deobf.NameMapper; import jadx.core.dex.attributes.AFlag; +import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.EnumClassAttr; import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField; +import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.MethodInfo; @@ -41,6 +45,11 @@ public class EnumVisitor extends AbstractVisitor { @Override public boolean visit(ClassNode cls) throws JadxException { if (!cls.isEnum()) { + AccessInfo accessFlags = cls.getAccessFlags(); + if (accessFlags.isEnum()) { + cls.setAccessFlags(accessFlags.remove(AccessFlags.ACC_ENUM)); + cls.addAttr(AType.COMMENTS, "'enum' access flag removed"); + } return true; } // search class init method diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java b/jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java index cd270f92188fe217728e53202db01f2d938b531e..4e9b43826cfb0d2dd4dcf65237a8213814f6e111 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java @@ -28,7 +28,7 @@ public class FixAccessModifiers extends AbstractVisitor { return; } int newVisFlag = fixVisibility(mth); - if (newVisFlag != 0) { + if (newVisFlag != -1) { changeVisibility(mth, newVisFlag); } } @@ -38,7 +38,7 @@ public class FixAccessModifiers extends AbstractVisitor { AccessInfo newAccFlags = accessFlags.changeVisibility(newVisFlag); if (newAccFlags != accessFlags) { node.setAccessFlags(newAccFlags); - node.addAttr(AType.COMMENTS, "access modifiers changed from: " + accessFlags.rawString()); + node.addAttr(AType.COMMENTS, "access modifiers changed from: " + accessFlags.getVisibility().rawString()); } } @@ -52,9 +52,15 @@ public class FixAccessModifiers extends AbstractVisitor { // make abstract methods public return AccessFlags.ACC_PUBLIC; } + // enum constructor can't be public + if (accessFlags.isConstructor() + && accessFlags.isPublic() + && mth.getParentClass().isEnum()) { + return 0; + } if (accessFlags.isConstructor() || accessFlags.isStatic()) { // TODO: make public if used outside - return 0; + return -1; } // make other direct methods private return AccessFlags.ACC_PRIVATE; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java index 7cfae511419351e716aee96c7c459a5c6541a076..fbe6f45b70f3669d3bcd6aae5ced063eaad4b5c2 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java @@ -103,7 +103,9 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor } RegisterArg initArg = phiInsn.getArg(0); InsnNode initInsn = initArg.getAssignInsn(); - if (initInsn == null || initArg.getSVar().getUseCount() != 1) { + if (initInsn == null + || initInsn.contains(AFlag.DONT_GENERATE) + || initArg.getSVar().getUseCount() != 1) { return false; } if (!usedOnlyInLoop(mth, loopRegion, arg)) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/enums/TestEnums3.java b/jadx-core/src/test/java/jadx/tests/integration/enums/TestEnums3.java index 50810c759fb47a85448fd8116efa03edc5769c54..963f03fcce000bebfb9d0bd4a2dd784f172ac9e9 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/enums/TestEnums3.java +++ b/jadx-core/src/test/java/jadx/tests/integration/enums/TestEnums3.java @@ -44,6 +44,6 @@ public class TestEnums3 extends IntegrationTest { assertThat(code, containsOne("ONE(1)")); // assertThat(code, containsOne("THREE(three)")); // assertThat(code, containsOne("assertTrue(Numbers.ONE.getNum() == 1);")); - assertThat(code, containsOne("private Numbers(int n) {")); + assertThat(code, containsOne("Numbers(int n) {")); } }