From 85760cc844be7b7092cf8be37be8b9759ab31d8d Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 12 May 2020 17:17:22 +0100 Subject: [PATCH] fix: replace type variables in arrays (#913) --- .../core/dex/instructions/args/ArgType.java | 4 +- .../jadx/core/dex/nodes/utils/TypeUtils.java | 7 +++ .../core/dex/nodes/utils/TypeUtilsTest.java | 45 +++++++++++++++++++ .../generics/TestMethodOverride.java | 3 +- .../smali/generics/TestMethodOverride.smali | 9 ++++ 5 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/core/dex/nodes/utils/TypeUtilsTest.java diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java index cdeb21075..2ffec4f7a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java @@ -5,6 +5,8 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import org.jetbrains.annotations.NotNull; + import jadx.core.Consts; import jadx.core.dex.info.ClassInfo; import jadx.core.dex.nodes.ClassNode; @@ -114,7 +116,7 @@ public abstract class ArgType { return new OuterGenericObject((GenericObject) genericOuterType, (ObjectType) innerType); } - public static ArgType array(ArgType vtype) { + public static ArgType array(@NotNull ArgType vtype) { return new ArrayArg(vtype); } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/utils/TypeUtils.java b/jadx-core/src/main/java/jadx/core/dex/nodes/utils/TypeUtils.java index e7e1f4449..2291ee2c0 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/utils/TypeUtils.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/utils/TypeUtils.java @@ -117,6 +117,13 @@ public class TypeUtils { if (replaceType.isGenericType()) { return replaceMap.get(replaceType); } + if (replaceType.isArray()) { + ArgType replaced = replaceTypeVariablesUsingMap(replaceType.getArrayElement(), replaceMap); + if (replaced == null) { + return null; + } + return ArgType.array(replaced); + } ArgType wildcardType = replaceType.getWildcardType(); if (wildcardType != null && wildcardType.containsTypeVariable()) { diff --git a/jadx-core/src/test/java/jadx/core/dex/nodes/utils/TypeUtilsTest.java b/jadx-core/src/test/java/jadx/core/dex/nodes/utils/TypeUtilsTest.java new file mode 100644 index 000000000..003975c48 --- /dev/null +++ b/jadx-core/src/test/java/jadx/core/dex/nodes/utils/TypeUtilsTest.java @@ -0,0 +1,45 @@ +package jadx.core.dex.nodes.utils; + +import java.util.Collections; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jadx.api.JadxArgs; +import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.nodes.RootNode; + +import static jadx.core.dex.instructions.args.ArgType.STRING; +import static jadx.core.dex.instructions.args.ArgType.array; +import static jadx.core.dex.instructions.args.ArgType.generic; +import static jadx.core.dex.instructions.args.ArgType.genericType; +import static jadx.core.dex.instructions.args.ArgType.object; +import static org.assertj.core.api.Assertions.assertThat; + +class TypeUtilsTest { + private TypeUtils typeUtils; + + @BeforeEach + public void init() { + typeUtils = new TypeUtils(new RootNode(new JadxArgs())); + } + + @Test + void replaceTypeVariablesUsingMap() { + ArgType typeVar = genericType("T"); + ArgType listCls = object("java.util.List"); + Map typeMap = Collections.singletonMap(typeVar, STRING); + + replaceTypeVar(typeVar, typeMap, STRING); + replaceTypeVar(generic(listCls, typeVar), typeMap, generic(listCls, STRING)); + replaceTypeVar(array(typeVar), typeMap, array(STRING)); + } + + private void replaceTypeVar(ArgType typeVar, Map typeMap, ArgType expected) { + ArgType resultType = typeUtils.replaceTypeVariablesUsingMap(typeVar, typeMap); + assertThat(resultType) + .as("Replace %s using map %s", typeVar, typeMap) + .isEqualTo(expected); + } +} diff --git a/jadx-core/src/test/java/jadx/tests/integration/generics/TestMethodOverride.java b/jadx-core/src/test/java/jadx/tests/integration/generics/TestMethodOverride.java index 0d7887fe7..58d172087 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/generics/TestMethodOverride.java +++ b/jadx-core/src/test/java/jadx/tests/integration/generics/TestMethodOverride.java @@ -15,6 +15,7 @@ public class TestMethodOverride extends SmaliTest { assertThat(getClassNodeFromSmali()) .code() .containsOne("String createFromParcel(Parcel parcel) {") - .containsOne("@Override"); + .containsOne("String[] newArray(int i) {") + .countString(2, "@Override"); } } diff --git a/jadx-core/src/test/smali/generics/TestMethodOverride.smali b/jadx-core/src/test/smali/generics/TestMethodOverride.smali index 942bf87d1..1c5821571 100644 --- a/jadx-core/src/test/smali/generics/TestMethodOverride.smali +++ b/jadx-core/src/test/smali/generics/TestMethodOverride.smali @@ -36,3 +36,12 @@ return-object v0 .end method +.method public final synthetic newArray(I)[Ljava/lang/Object; + .registers 2 + + .line 4 + new-array p1, p1, [Ljava/lang/String; + + return-object p1 +.end method +