Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
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
b689efcc
Commit
b689efcc
authored
Feb 11, 2019
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: forbid to change types for methods arguments
parent
89563b62
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
81 additions
and
49 deletions
+81
-49
CodeVar.java
...rc/main/java/jadx/core/dex/instructions/args/CodeVar.java
+1
-1
SSAVar.java
...src/main/java/jadx/core/dex/instructions/args/SSAVar.java
+3
-0
InitCodeVariables.java
...c/main/java/jadx/core/dex/visitors/InitCodeVariables.java
+26
-4
TypeInferenceVisitor.java
...core/dex/visitors/typeinference/TypeInferenceVisitor.java
+35
-28
TypeInfo.java
...n/java/jadx/core/dex/visitors/typeinference/TypeInfo.java
+2
-2
TypeUpdate.java
...java/jadx/core/dex/visitors/typeinference/TypeUpdate.java
+8
-8
TestTryCatchFinally6.java
...jadx/tests/integration/trycatch/TestTryCatchFinally6.java
+4
-4
TestVariablesGeneric.java
...adx/tests/integration/variables/TestVariablesGeneric.java
+1
-1
TestVariablesGeneric.smali
...-core/src/test/smali/variables/TestVariablesGeneric.smali
+1
-1
No files found.
jadx-core/src/main/java/jadx/core/dex/instructions/args/CodeVar.java
View file @
b689efcc
...
@@ -6,7 +6,7 @@ import java.util.List;
...
@@ -6,7 +6,7 @@ import java.util.List;
public
class
CodeVar
{
public
class
CodeVar
{
private
String
name
;
private
String
name
;
private
ArgType
type
;
private
ArgType
type
;
// nullable before type inference, set only for immutable types
private
List
<
SSAVar
>
ssaVars
=
new
ArrayList
<>(
3
);
private
List
<
SSAVar
>
ssaVars
=
new
ArrayList
<>(
3
);
private
boolean
isFinal
;
private
boolean
isFinal
;
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java
View file @
b689efcc
...
@@ -139,6 +139,9 @@ public class SSAVar extends AttrNode {
...
@@ -139,6 +139,9 @@ public class SSAVar extends AttrNode {
public
void
setCodeVar
(
@NotNull
CodeVar
codeVar
)
{
public
void
setCodeVar
(
@NotNull
CodeVar
codeVar
)
{
this
.
codeVar
=
codeVar
;
this
.
codeVar
=
codeVar
;
if
(
codeVar
.
getType
()
!=
null
&&
!
typeInfo
.
getType
().
equals
(
codeVar
.
getType
()))
{
throw
new
JadxRuntimeException
(
"Unmached types for SSA and Code variables: "
+
this
+
" and "
+
codeVar
);
}
codeVar
.
addSsaVar
(
this
);
codeVar
.
addSsaVar
(
this
);
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/InitCodeVariables.java
View file @
b689efcc
package
jadx
.
core
.
dex
.
visitors
;
package
jadx
.
core
.
dex
.
visitors
;
import
java.util.HashSet
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.instructions.PhiInsn
;
import
jadx.core.dex.instructions.PhiInsn
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.CodeVar
;
import
jadx.core.dex.instructions.args.CodeVar
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
@JadxVisitor
(
@JadxVisitor
(
name
=
"InitCodeVariables"
,
name
=
"InitCodeVariables"
,
...
@@ -41,7 +45,6 @@ public class InitCodeVariables extends AbstractVisitor {
...
@@ -41,7 +45,6 @@ public class InitCodeVariables extends AbstractVisitor {
return
;
return
;
}
}
CodeVar
codeVar
=
new
CodeVar
();
CodeVar
codeVar
=
new
CodeVar
();
codeVar
.
setType
(
ssaVar
.
getTypeInfo
().
getType
());
RegisterArg
assignArg
=
ssaVar
.
getAssign
();
RegisterArg
assignArg
=
ssaVar
.
getAssign
();
if
(
assignArg
.
contains
(
AFlag
.
THIS
))
{
if
(
assignArg
.
contains
(
AFlag
.
THIS
))
{
codeVar
.
setName
(
RegisterArg
.
THIS_ARG_NAME
);
codeVar
.
setName
(
RegisterArg
.
THIS_ARG_NAME
);
...
@@ -55,17 +58,36 @@ public class InitCodeVariables extends AbstractVisitor {
...
@@ -55,17 +58,36 @@ public class InitCodeVariables extends AbstractVisitor {
}
}
private
static
void
setCodeVar
(
SSAVar
ssaVar
,
CodeVar
codeVar
)
{
private
static
void
setCodeVar
(
SSAVar
ssaVar
,
CodeVar
codeVar
)
{
ssaVar
.
setCodeVar
(
codeVar
);
PhiInsn
usedInPhi
=
ssaVar
.
getUsedInPhi
();
PhiInsn
usedInPhi
=
ssaVar
.
getUsedInPhi
();
if
(
usedInPhi
!=
null
)
{
if
(
usedInPhi
!=
null
)
{
Set
<
SSAVar
>
vars
=
new
HashSet
<>();
Set
<
SSAVar
>
vars
=
new
LinkedHashSet
<>();
vars
.
add
(
ssaVar
);
collectConnectedVars
(
usedInPhi
,
vars
);
collectConnectedVars
(
usedInPhi
,
vars
);
setCodeVarType
(
codeVar
,
vars
);
vars
.
forEach
(
var
->
{
vars
.
forEach
(
var
->
{
if
(
var
.
isCodeVarSet
())
{
if
(
var
.
isCodeVarSet
())
{
codeVar
.
mergeFlagsFrom
(
var
.
getCodeVar
());
codeVar
.
mergeFlagsFrom
(
var
.
getCodeVar
());
}
}
var
.
setCodeVar
(
codeVar
);
var
.
setCodeVar
(
codeVar
);
});
});
}
else
{
ssaVar
.
setCodeVar
(
codeVar
);
}
}
private
static
void
setCodeVarType
(
CodeVar
codeVar
,
Set
<
SSAVar
>
vars
)
{
if
(
vars
.
size
()
>
1
)
{
List
<
ArgType
>
imTypes
=
vars
.
stream
()
.
filter
(
var
->
var
.
contains
(
AFlag
.
METHOD_ARGUMENT
))
.
map
(
var
->
var
.
getTypeInfo
().
getType
())
.
distinct
()
.
collect
(
Collectors
.
toList
());
int
imCount
=
imTypes
.
size
();
if
(
imCount
==
1
)
{
codeVar
.
setType
(
imTypes
.
get
(
0
));
}
else
if
(
imCount
>
1
)
{
throw
new
JadxRuntimeException
(
"Several immutable types in one variable: "
+
imTypes
+
", vars: "
+
vars
);
}
}
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java
View file @
b689efcc
...
@@ -102,51 +102,58 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
...
@@ -102,51 +102,58 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
private
boolean
setBestType
(
SSAVar
ssaVar
)
{
private
boolean
setBestType
(
SSAVar
ssaVar
)
{
try
{
try
{
RegisterArg
assignArg
=
ssaVar
.
getAssign
();
ArgType
codeVarType
=
ssaVar
.
getCodeVar
().
getType
();
if
(
!
assignArg
.
isTypeImmutable
()
)
{
if
(
codeVarType
!=
null
)
{
return
calculateFromBounds
(
ssaVar
);
return
applyImmutableType
(
ssaVar
,
codeVarType
);
}
}
ArgType
initType
=
assignArg
.
getInitType
();
RegisterArg
assignArg
=
ssaVar
.
getAssign
();
TypeUpdateResult
result
=
typeUpdate
.
apply
(
ssaVar
,
initType
);
if
(
assignArg
.
isTypeImmutable
())
{
if
(
result
==
TypeUpdateResult
.
REJECT
)
{
return
applyImmutableType
(
ssaVar
,
assignArg
.
getInitType
());
if
(
Consts
.
DEBUG
)
{
LOG
.
info
(
"Initial immutable type set rejected: {} -> {}"
,
ssaVar
,
initType
);
}
return
false
;
}
}
return
true
;
return
calculateFromBounds
(
ssaVar
)
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to calculate best type for var: {}"
,
ssaVar
);
LOG
.
error
(
"Failed to calculate best type for var: {}"
,
ssaVar
);
return
false
;
return
false
;
}
}
}
}
private
boolean
applyImmutableType
(
SSAVar
ssaVar
,
ArgType
initType
)
{
TypeUpdateResult
result
=
typeUpdate
.
apply
(
ssaVar
,
initType
);
if
(
result
==
TypeUpdateResult
.
REJECT
)
{
if
(
Consts
.
DEBUG
)
{
LOG
.
info
(
"Initial immutable type set rejected: {} -> {}"
,
ssaVar
,
initType
);
}
return
false
;
}
return
result
==
TypeUpdateResult
.
CHANGED
;
}
private
boolean
calculateFromBounds
(
SSAVar
ssaVar
)
{
private
boolean
calculateFromBounds
(
SSAVar
ssaVar
)
{
TypeInfo
typeInfo
=
ssaVar
.
getTypeInfo
();
TypeInfo
typeInfo
=
ssaVar
.
getTypeInfo
();
Set
<
ITypeBound
>
bounds
=
typeInfo
.
getBounds
();
Set
<
ITypeBound
>
bounds
=
typeInfo
.
getBounds
();
Optional
<
ArgType
>
bestTypeOpt
=
selectBestTypeFromBounds
(
bounds
);
Optional
<
ArgType
>
bestTypeOpt
=
selectBestTypeFromBounds
(
bounds
);
if
(
bestTypeOpt
.
isPresent
())
{
if
(!
bestTypeOpt
.
isPresent
())
{
ArgType
candidateType
=
bestTypeOpt
.
get
();
if
(
Consts
.
DEBUG
)
{
TypeUpdateResult
result
=
typeUpdate
.
apply
(
ssaVar
,
candidateType
);
LOG
.
warn
(
"Failed to select best type from bounds, count={} : "
,
bounds
.
size
());
if
(
result
==
TypeUpdateResult
.
REJECT
)
{
for
(
ITypeBound
bound
:
bounds
)
{
if
(
Consts
.
DEBUG
)
{
LOG
.
warn
(
" {}"
,
bound
);
if
(
ssaVar
.
getTypeInfo
().
getType
().
equals
(
candidateType
))
{
LOG
.
info
(
"Same type rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
else
if
(
candidateType
.
isTypeKnown
())
{
LOG
.
debug
(
"Type set rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
}
}
return
false
;
}
}
return
result
==
TypeUpdateResult
.
CHANGED
;
return
false
;
}
}
if
(
Consts
.
DEBUG
)
{
ArgType
candidateType
=
bestTypeOpt
.
get
();
LOG
.
warn
(
"Failed to select best type from bounds, count={} : "
,
bounds
.
size
());
TypeUpdateResult
result
=
typeUpdate
.
apply
(
ssaVar
,
candidateType
);
for
(
ITypeBound
bound
:
bounds
)
{
if
(
result
==
TypeUpdateResult
.
REJECT
)
{
LOG
.
warn
(
" {}"
,
bound
);
if
(
Consts
.
DEBUG
)
{
if
(
ssaVar
.
getTypeInfo
().
getType
().
equals
(
candidateType
))
{
LOG
.
info
(
"Same type rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
else
if
(
candidateType
.
isTypeKnown
())
{
LOG
.
debug
(
"Type set rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
}
}
return
false
;
}
}
return
false
;
return
result
==
TypeUpdateResult
.
CHANGED
;
}
}
private
Optional
<
ArgType
>
selectBestTypeFromBounds
(
Set
<
ITypeBound
>
bounds
)
{
private
Optional
<
ArgType
>
selectBestTypeFromBounds
(
Set
<
ITypeBound
>
bounds
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInfo.java
View file @
b689efcc
package
jadx
.
core
.
dex
.
visitors
.
typeinference
;
package
jadx
.
core
.
dex
.
visitors
.
typeinference
;
import
java.util.HashSet
;
import
java.util.
Linked
HashSet
;
import
java.util.Set
;
import
java.util.Set
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.NotNull
;
...
@@ -10,7 +10,7 @@ import jadx.core.dex.instructions.args.ArgType;
...
@@ -10,7 +10,7 @@ import jadx.core.dex.instructions.args.ArgType;
public
class
TypeInfo
{
public
class
TypeInfo
{
private
ArgType
type
=
ArgType
.
UNKNOWN
;
private
ArgType
type
=
ArgType
.
UNKNOWN
;
private
final
Set
<
ITypeBound
>
bounds
=
new
HashSet
<>();
private
final
Set
<
ITypeBound
>
bounds
=
new
Linked
HashSet
<>();
@NotNull
@NotNull
public
ArgType
getType
()
{
public
ArgType
getType
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java
View file @
b689efcc
...
@@ -48,7 +48,7 @@ public final class TypeUpdate {
...
@@ -48,7 +48,7 @@ public final class TypeUpdate {
if
(
candidateType
==
null
)
{
if
(
candidateType
==
null
)
{
return
REJECT
;
return
REJECT
;
}
}
if
(!
candidateType
.
isTypeKnown
()
&&
ssaVar
.
getTypeInfo
().
getType
().
isTypeKnown
()
)
{
if
(!
candidateType
.
isTypeKnown
()
/* && ssaVar.getTypeInfo().getType().isTypeKnown()*/
)
{
return
REJECT
;
return
REJECT
;
}
}
...
@@ -86,14 +86,14 @@ public final class TypeUpdate {
...
@@ -86,14 +86,14 @@ public final class TypeUpdate {
return
SAME
;
return
SAME
;
}
}
TypeCompareEnum
compareResult
=
comparator
.
compareTypes
(
candidateType
,
currentType
);
TypeCompareEnum
compareResult
=
comparator
.
compareTypes
(
candidateType
,
currentType
);
if
(
compareResult
==
TypeCompareEnum
.
CONFLICT
)
{
if
(
Consts
.
DEBUG
)
{
LOG
.
debug
(
"Type rejected for {} due to conflict: candidate={}, current={}"
,
arg
,
candidateType
,
currentType
);
}
return
REJECT
;
}
if
(
arg
.
isTypeImmutable
()
&&
currentType
!=
ArgType
.
UNKNOWN
)
{
if
(
arg
.
isTypeImmutable
()
&&
currentType
!=
ArgType
.
UNKNOWN
)
{
// don't changed type, conflict already rejected
// don't changed type
if
(
compareResult
==
TypeCompareEnum
.
CONFLICT
)
{
if
(
Consts
.
DEBUG
)
{
LOG
.
debug
(
"Type rejected for {} due to conflict: candidate={}, current={}"
,
arg
,
candidateType
,
currentType
);
}
return
REJECT
;
}
return
SAME
;
return
SAME
;
}
}
if
(
compareResult
.
isWider
())
{
if
(
compareResult
.
isWider
())
{
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally6.java
View file @
b689efcc
...
@@ -56,13 +56,13 @@ public class TestTryCatchFinally6 extends IntegrationTest {
...
@@ -56,13 +56,13 @@ public class TestTryCatchFinally6 extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsLines
(
2
,
assertThat
(
code
,
containsLines
(
2
,
"
FileInputStream fileI
nputStream = null;"
,
"
InputStream i
nputStream = null;"
,
"try {"
,
"try {"
,
indent
()
+
"call();"
,
indent
()
+
"call();"
,
indent
()
+
"
fileI
nputStream = new FileInputStream(\"1.txt\");"
,
indent
()
+
"
i
nputStream = new FileInputStream(\"1.txt\");"
,
"} finally {"
,
"} finally {"
,
indent
()
+
"if (
fileI
nputStream != null) {"
,
indent
()
+
"if (
i
nputStream != null) {"
,
indent
()
+
indent
()
+
"
fileI
nputStream.close();"
,
indent
()
+
indent
()
+
"
i
nputStream.close();"
,
indent
()
+
"}"
,
indent
()
+
"}"
,
"}"
"}"
));
));
...
...
jadx-core/src/test/java/jadx/tests/integration/variables/TestVariablesGeneric.java
View file @
b689efcc
...
@@ -24,7 +24,7 @@ public class TestVariablesGeneric extends SmaliTest {
...
@@ -24,7 +24,7 @@ public class TestVariablesGeneric extends SmaliTest {
@Test
@Test
public
void
test
()
{
public
void
test
()
{
disableCompilation
();
disableCompilation
();
ClassNode
cls
=
getClassNodeFromSmaliWithP
ath
(
"variables"
,
"TestVariablesGeneric"
);
ClassNode
cls
=
getClassNodeFromSmaliWithP
kg
(
"variables"
,
"TestVariablesGeneric"
);
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
not
(
containsString
(
"iVar2"
)));
assertThat
(
code
,
not
(
containsString
(
"iVar2"
)));
...
...
jadx-core/src/test/smali/variables/TestVariablesGeneric.smali
View file @
b689efcc
.class public LTestVariablesGeneric;
.class public L
variables/
TestVariablesGeneric;
.super Ljava/lang/Object;
.super Ljava/lang/Object;
.source "SourceFile"
.source "SourceFile"
...
...
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