Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
f846df53
Commit
f846df53
authored
May 03, 2019
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: rename field if collide with any root package (#647)
parent
4a39af7c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
199 additions
and
69 deletions
+199
-69
RenameVisitor.java
...e/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
+43
-0
IntegrationTest.java
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
+34
-33
SmaliTest.java
jadx-core/src/test/java/jadx/tests/api/SmaliTest.java
+1
-3
DynamicCompiler.java
...rc/test/java/jadx/tests/api/compiler/DynamicCompiler.java
+28
-26
TestBreakWithLabel.java
...java/jadx/tests/integration/loops/TestBreakWithLabel.java
+6
-7
TestFieldCollideWithPackage.java
.../tests/integration/names/TestFieldCollideWithPackage.java
+62
-0
1.smali
.../src/test/smali/names/TestFieldCollideWithPackage/1.smali
+15
-0
2.smali
.../src/test/smali/names/TestFieldCollideWithPackage/2.smali
+10
-0
No files found.
jadx-core/src/main/java/jadx/core/dex/visitors/RenameVisitor.java
View file @
f846df53
...
...
@@ -5,6 +5,8 @@ import java.util.HashSet;
import
java.util.List
;
import
java.util.Set
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.api.JadxArgs
;
import
jadx.core.Consts
;
import
jadx.core.deobf.Deobfuscator
;
...
...
@@ -65,6 +67,9 @@ public class RenameVisitor extends AbstractVisitor {
}
}
}
if
(
args
.
isRenameValid
())
{
checkFieldsCollisionWithRootPackage
(
classes
);
}
}
private
void
checkClassName
(
ClassNode
cls
,
JadxArgs
args
)
{
...
...
@@ -134,4 +139,42 @@ public class RenameVisitor extends AbstractVisitor {
}
}
}
private
void
checkFieldsCollisionWithRootPackage
(
List
<
ClassNode
>
classes
)
{
Set
<
String
>
rootPkgs
=
collectRootPkgs
(
classes
);
for
(
ClassNode
cls
:
classes
)
{
for
(
FieldNode
field
:
cls
.
getFields
())
{
if
(
rootPkgs
.
contains
(
field
.
getAlias
()))
{
deobfuscator
.
forceRenameField
(
field
);
}
}
}
}
private
static
Set
<
String
>
collectRootPkgs
(
List
<
ClassNode
>
classes
)
{
Set
<
String
>
fullPkgs
=
new
HashSet
<>();
for
(
ClassNode
cls
:
classes
)
{
fullPkgs
.
add
(
cls
.
getAlias
().
getPackage
());
}
Set
<
String
>
rootPkgs
=
new
HashSet
<>();
for
(
String
pkg
:
fullPkgs
)
{
String
rootPkg
=
getRootPkg
(
pkg
);
if
(
rootPkg
!=
null
)
{
rootPkgs
.
add
(
rootPkg
);
}
}
return
rootPkgs
;
}
@Nullable
private
static
String
getRootPkg
(
String
pkg
)
{
if
(
pkg
.
isEmpty
())
{
return
null
;
}
int
dotPos
=
pkg
.
indexOf
(
'.'
);
if
(
dotPos
<
0
)
{
return
pkg
;
}
return
pkg
.
substring
(
0
,
dotPos
);
}
}
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
View file @
f846df53
...
...
@@ -124,10 +124,20 @@ public abstract class IntegrationTest extends TestUtils {
assertThat
(
"Class not found: "
+
clsName
,
cls
,
notNullValue
());
assertThat
(
clsName
,
is
(
cls
.
getClassInfo
().
getFullName
()));
decompileAndCheck
Cls
(
d
,
cls
);
decompileAndCheck
(
d
,
Collections
.
singletonList
(
cls
)
);
return
cls
;
}
public
ClassNode
searchCls
(
List
<
ClassNode
>
list
,
String
fullClsName
)
{
for
(
ClassNode
cls
:
list
)
{
if
(
cls
.
getClassInfo
().
getFullName
().
equals
(
fullClsName
))
{
return
cls
;
}
}
fail
(
"Class not found by name "
+
fullClsName
+
" in list: "
+
list
);
return
null
;
}
protected
JadxDecompiler
loadFiles
(
List
<
File
>
inputFiles
)
{
JadxDecompiler
d
=
null
;
try
{
...
...
@@ -137,26 +147,29 @@ public abstract class IntegrationTest extends TestUtils {
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
fail
(
e
.
getMessage
());
return
null
;
}
RootNode
root
=
JadxInternalAccess
.
getRoot
(
d
);
insertResources
(
root
);
return
d
;
}
protected
void
decompileAndCheck
Cls
(
JadxDecompiler
d
,
ClassNode
cls
)
{
protected
void
decompileAndCheck
(
JadxDecompiler
d
,
List
<
ClassNode
>
clsList
)
{
if
(
unloadCls
)
{
decompile
(
d
,
cls
);
clsList
.
forEach
(
cls
->
decompile
(
d
,
cls
)
);
}
else
{
decompileWithoutUnload
(
d
,
cls
);
clsList
.
forEach
(
cls
->
decompileWithoutUnload
(
d
,
cls
)
);
}
System
.
out
.
println
(
"-----------------------------------------------------------"
);
System
.
out
.
println
(
cls
.
getCode
());
for
(
ClassNode
cls
:
clsList
)
{
System
.
out
.
println
(
"-----------------------------------------------------------"
);
System
.
out
.
println
(
cls
.
getCode
());
}
System
.
out
.
println
(
"-----------------------------------------------------------"
);
c
heckCode
(
cls
);
compile
(
cls
);
runAutoCheck
(
cls
.
getClassInfo
().
getFullName
()
);
c
lsList
.
forEach
(
IntegrationTest:
:
checkCode
);
compile
(
cls
List
);
clsList
.
forEach
(
this
::
runAutoCheck
);
}
private
void
insertResources
(
RootNode
root
)
{
...
...
@@ -221,7 +234,8 @@ public abstract class IntegrationTest extends TestUtils {
return
false
;
}
private
void
runAutoCheck
(
String
clsName
)
{
private
void
runAutoCheck
(
ClassNode
cls
)
{
String
clsName
=
cls
.
getClassInfo
().
getFullName
();
try
{
// run 'check' method from original class
Class
<?>
origCls
;
...
...
@@ -252,7 +266,7 @@ public abstract class IntegrationTest extends TestUtils {
// run 'check' method from decompiled class
if
(
compile
)
{
try
{
limitExecTime
(()
->
invoke
(
"check"
));
limitExecTime
(()
->
invoke
(
cls
,
"check"
));
}
catch
(
Exception
e
)
{
rethrow
(
"Decompiled check failed"
,
e
);
}
...
...
@@ -306,11 +320,15 @@ public abstract class IntegrationTest extends TestUtils {
}
void
compile
(
ClassNode
cls
)
{
compile
(
Collections
.
singletonList
(
cls
));
}
void
compile
(
List
<
ClassNode
>
clsList
)
{
if
(!
compile
)
{
return
;
}
try
{
dynamicCompiler
=
new
DynamicCompiler
(
cls
);
dynamicCompiler
=
new
DynamicCompiler
(
cls
List
);
boolean
result
=
dynamicCompiler
.
compile
();
assertTrue
(
result
,
"Compilation failed"
);
System
.
out
.
println
(
"Compilation: PASSED"
);
...
...
@@ -319,30 +337,13 @@ public abstract class IntegrationTest extends TestUtils {
}
}
public
Object
invoke
(
String
method
)
throws
Exception
{
return
invoke
(
method
,
new
Class
<?>[
0
]);
}
public
Object
invoke
(
String
method
,
Class
<?>[]
types
,
Object
...
args
)
throws
Exception
{
Method
mth
=
getReflectMethod
(
method
,
types
);
return
invoke
(
mth
,
args
);
}
public
Method
getReflectMethod
(
String
method
,
Class
<?>...
types
)
{
assertNotNull
(
dynamicCompiler
,
"dynamicCompiler not ready"
);
try
{
return
dynamicCompiler
.
getMethod
(
method
,
types
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
fail
(
e
.
getMessage
());
}
return
null
;
public
Object
invoke
(
ClassNode
cls
,
String
method
)
throws
Exception
{
return
invoke
(
cls
,
method
,
new
Class
<?>[
0
]);
}
public
Object
invoke
(
Method
mth
,
Object
...
args
)
throws
Exception
{
public
Object
invoke
(
ClassNode
cls
,
String
methodName
,
Class
<?>[]
types
,
Object
...
args
)
throws
Exception
{
assertNotNull
(
dynamicCompiler
,
"dynamicCompiler not ready"
);
assertNotNull
(
mth
,
"unknown method"
);
return
dynamicCompiler
.
invoke
(
mth
,
args
);
return
dynamicCompiler
.
invoke
(
cls
,
methodName
,
types
,
args
);
}
public
File
getJarForClass
(
Class
<?>
cls
)
throws
IOException
{
...
...
jadx-core/src/test/java/jadx/tests/api/SmaliTest.java
View file @
f846df53
...
...
@@ -56,9 +56,7 @@ public abstract class SmaliTest extends IntegrationTest {
JadxDecompiler
d
=
loadFiles
(
Collections
.
singletonList
(
outDex
));
RootNode
root
=
JadxInternalAccess
.
getRoot
(
d
);
List
<
ClassNode
>
classes
=
root
.
getClasses
(
false
);
for
(
ClassNode
cls
:
classes
)
{
decompileAndCheckCls
(
d
,
cls
);
}
decompileAndCheck
(
d
,
classes
);
return
classes
;
}
...
...
jadx-core/src/test/java/jadx/tests/api/compiler/DynamicCompiler.java
View file @
f846df53
...
...
@@ -2,6 +2,7 @@ package jadx.tests.api.compiler;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
javax.tools.JavaCompiler
;
...
...
@@ -9,31 +10,28 @@ import javax.tools.JavaFileManager;
import
javax.tools.JavaFileObject
;
import
javax.tools.ToolProvider
;
import
org.jetbrains.annotations.NotNull
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.nodes.ClassNode
;
import
static
javax
.
tools
.
JavaCompiler
.
CompilationTask
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNotNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
fail
;
public
class
DynamicCompiler
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
DynamicCompiler
.
class
);
private
final
ClassNode
clsNode
;
private
final
List
<
ClassNode
>
clsNodeList
;
private
JavaFileManager
fileManager
;
private
Object
instance
;
public
DynamicCompiler
(
ClassNode
clsNode
)
{
this
.
clsNode
=
clsNode
;
public
DynamicCompiler
(
List
<
ClassNode
>
clsNodeList
)
{
this
.
clsNodeList
=
clsNodeList
;
}
public
boolean
compile
()
throws
Exception
{
String
fullName
=
clsNode
.
getFullName
();
String
code
=
clsNode
.
getCode
().
toString
();
public
boolean
compile
()
{
JavaCompiler
compiler
=
ToolProvider
.
getSystemJavaCompiler
();
if
(
compiler
==
null
)
{
LOG
.
error
(
"Can not find compiler, please use JDK instead"
);
...
...
@@ -41,8 +39,10 @@ public class DynamicCompiler {
}
fileManager
=
new
ClassFileManager
(
compiler
.
getStandardFileManager
(
null
,
null
,
null
));
List
<
JavaFileObject
>
jFiles
=
new
ArrayList
<>(
1
);
jFiles
.
add
(
new
CharSequenceJavaFileObject
(
fullName
,
code
));
List
<
JavaFileObject
>
jFiles
=
new
ArrayList
<>(
clsNodeList
.
size
());
for
(
ClassNode
clsNode
:
clsNodeList
)
{
jFiles
.
add
(
new
CharSequenceJavaFileObject
(
clsNode
.
getFullName
(),
clsNode
.
getCode
().
toString
()));
}
CompilationTask
compilerTask
=
compiler
.
getTask
(
null
,
fileManager
,
null
,
null
,
null
,
jFiles
);
return
Boolean
.
TRUE
.
equals
(
compilerTask
.
call
());
...
...
@@ -52,27 +52,29 @@ public class DynamicCompiler {
return
fileManager
.
getClassLoader
(
null
);
}
p
rivate
void
makeInstance
(
)
throws
Exception
{
String
fullName
=
cls
Node
.
getFullName
();
instance
=
getClassLoader
().
loadClass
(
fullName
).
getConstructor
().
newInstance
();
p
ublic
Object
makeInstance
(
ClassNode
cls
)
throws
Exception
{
String
fullName
=
cls
.
getFullName
();
return
getClassLoader
().
loadClass
(
fullName
).
getConstructor
().
newInstance
();
}
private
Object
getInstance
()
throws
Exception
{
if
(
instance
==
null
)
{
makeInstance
();
}
return
instance
;
}
public
Method
getMethod
(
String
method
,
Class
<?>[]
types
)
throws
Exception
{
@NotNull
public
Method
getMethod
(
Object
inst
,
String
methodName
,
Class
<?>[]
types
)
throws
Exception
{
for
(
Class
<?>
type
:
types
)
{
checkType
(
type
);
}
return
getInstance
().
getClass
().
getMethod
(
method
,
types
);
return
inst
.
getClass
().
getMethod
(
methodName
,
types
);
}
public
Object
invoke
(
Method
mth
,
Object
...
args
)
throws
Exception
{
return
mth
.
invoke
(
getInstance
(),
args
);
public
Object
invoke
(
ClassNode
cls
,
String
methodName
,
Class
<?>[]
types
,
Object
[]
args
)
{
try
{
Object
inst
=
makeInstance
(
cls
);
Method
reflMth
=
getMethod
(
inst
,
methodName
,
types
);
assertNotNull
(
reflMth
,
"Failed to get method "
+
methodName
+
'('
+
Arrays
.
toString
(
types
)
+
')'
);
return
reflMth
.
invoke
(
inst
,
args
);
}
catch
(
Exception
e
)
{
fail
(
e
.
getMessage
(),
e
);
return
null
;
}
}
private
Class
<?>
checkType
(
Class
<?>
type
)
throws
ClassNotFoundException
{
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestBreakWithLabel.java
View file @
f846df53
package
jadx
.
tests
.
integration
.
loops
;
import
java.lang.reflect.Method
;
import
org.junit.jupiter.api.Test
;
import
jadx.core.dex.nodes.ClassNode
;
...
...
@@ -29,6 +27,12 @@ public class TestBreakWithLabel extends IntegrationTest {
System
.
out
.
println
(
"found: "
+
found
);
return
found
;
}
public
void
check
()
{
int
[][]
testArray
=
{
{
1
,
2
},
{
3
,
4
}
};
assertTrue
(
test
(
testArray
,
3
));
assertFalse
(
test
(
testArray
,
5
));
}
}
@Test
...
...
@@ -38,10 +42,5 @@ public class TestBreakWithLabel extends IntegrationTest {
assertThat
(
code
,
containsOne
(
"loop0:"
));
assertThat
(
code
,
containsOne
(
"break loop0;"
));
Method
test
=
getReflectMethod
(
"test"
,
int
[][].
class
,
int
.
class
);
int
[][]
testArray
=
{
{
1
,
2
},
{
3
,
4
}
};
assertTrue
((
Boolean
)
invoke
(
test
,
testArray
,
3
));
assertFalse
((
Boolean
)
invoke
(
test
,
testArray
,
5
));
}
}
jadx-core/src/test/java/jadx/tests/integration/names/TestFieldCollideWithPackage.java
0 → 100644
View file @
f846df53
package
jadx
.
tests
.
integration
.
names
;
import
java.util.List
;
import
org.junit.jupiter.api.Test
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.SmaliTest
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
not
;
public
class
TestFieldCollideWithPackage
extends
SmaliTest
{
//@formatter:off
/*
-----------------------------------------------------------
package first;
public class A {
public A first;
public second.A second;
public String test() {
return second.A.call(); // compiler treat 'second' as field name
}
}
-----------------------------------------------------------
package second;
public class A {
public static String call() {
return null;
}
}
-----------------------------------------------------------
*/
//@formatter:on
@Test
public
void
test
()
{
List
<
ClassNode
>
clsList
=
loadFromSmaliFiles
();
ClassNode
firstA
=
searchCls
(
clsList
,
"first.A"
);
String
code
=
firstA
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"second.A"
));
// expect field to be renamed
assertThat
(
code
,
not
(
containsString
(
"public second.A second;"
)));
}
@Test
public
void
testWithoutImports
()
{
getArgs
().
setUseImports
(
false
);
loadFromSmaliFiles
();
}
@Test
public
void
testWithDeobfuscation
()
{
enableDeobfuscation
();
loadFromSmaliFiles
();
}
}
jadx-core/src/test/smali/names/TestFieldCollideWithPackage/1.smali
0 → 100644
View file @
f846df53
.class public Lfirst/A;
.super Ljava/lang/Object;
.field public first:Lfirst/A;
.field public second:Lsecond/A;
.method public test()Ljava/lang/String;
.registers 2
invoke-static {}, Lsecond/A;->call()Ljava/lang/String;
move-result-object v0
return-object v0
.end method
jadx-core/src/test/smali/names/TestFieldCollideWithPackage/2.smali
0 → 100644
View file @
f846df53
.class public Lsecond/A;
.super Ljava/lang/Object;
.method static public call()Ljava/lang/String;
.registers 1
const v0, 0
return-object v0
.end method
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment