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
ebbe6db3
Commit
ebbe6db3
authored
Jul 12, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fix complex 'if' processing (issues #9 and #12)
parent
543cad3a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
632 additions
and
245 deletions
+632
-245
Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+5
-7
ConditionGen.java
jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java
+19
-8
AType.java
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
+3
-0
IfCondition.java
...core/src/main/java/jadx/core/dex/regions/IfCondition.java
+1
-6
IfInfo.java
jadx-core/src/main/java/jadx/core/dex/regions/IfInfo.java
+40
-17
CheckRegions.java
...ain/java/jadx/core/dex/visitors/regions/CheckRegions.java
+5
-9
IfMakerHelper.java
...in/java/jadx/core/dex/visitors/regions/IfMakerHelper.java
+190
-0
IfRegionVisitor.java
.../java/jadx/core/dex/visitors/regions/IfRegionVisitor.java
+32
-3
ProcessTryCatchRegions.java
...adx/core/dex/visitors/regions/ProcessTryCatchRegions.java
+1
-1
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+36
-186
ReturnVisitor.java
...in/java/jadx/core/dex/visitors/regions/ReturnVisitor.java
+3
-3
BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+12
-1
RegionUtils.java
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
+1
-1
TestConditions10.java
...java/jadx/tests/internal/conditions/TestConditions10.java
+45
-0
TestConditions11.java
...java/jadx/tests/internal/conditions/TestConditions11.java
+39
-0
TestConditions12.java
...java/jadx/tests/internal/conditions/TestConditions12.java
+71
-0
TestConditions13.java
...java/jadx/tests/internal/conditions/TestConditions13.java
+43
-0
TestConditions2.java
.../java/jadx/tests/internal/conditions/TestConditions2.java
+0
-1
TestConditions5.java
.../java/jadx/tests/internal/conditions/TestConditions5.java
+12
-0
TestConditions9.java
.../java/jadx/tests/internal/conditions/TestConditions9.java
+37
-0
TestSimpleConditions.java
.../jadx/tests/internal/conditions/TestSimpleConditions.java
+32
-0
TestLoopCondition2.java
...st/java/jadx/tests/internal/loops/TestLoopCondition2.java
+5
-2
No files found.
jadx-core/src/main/java/jadx/core/Jadx.java
View file @
ebbe6db3
...
...
@@ -60,17 +60,19 @@ public class Jadx {
passes
.
add
(
new
ConstInlinerVisitor
());
passes
.
add
(
new
FinishTypeInference
());
passes
.
add
(
new
EliminatePhiNodes
());
if
(
args
.
isRawCFGOutput
())
{
passes
.
add
(
new
DotGraphVisitor
(
outDir
,
false
,
true
));
}
passes
.
add
(
new
EliminatePhiNodes
());
passes
.
add
(
new
ModVisitor
());
passes
.
add
(
new
EnumVisitor
());
passes
.
add
(
new
CodeShrinker
());
if
(
args
.
isCFGOutput
())
{
passes
.
add
(
new
DotGraphVisitor
(
outDir
,
false
));
}
passes
.
add
(
new
RegionMakerVisitor
());
passes
.
add
(
new
IfRegionVisitor
());
passes
.
add
(
new
ReturnVisitor
());
...
...
@@ -87,10 +89,6 @@ public class Jadx {
passes
.
add
(
new
MethodInlineVisitor
());
passes
.
add
(
new
ClassModifier
());
passes
.
add
(
new
PrepareForCodeGen
());
if
(
args
.
isCFGOutput
())
{
passes
.
add
(
new
DotGraphVisitor
(
outDir
,
false
));
}
}
passes
.
add
(
new
CodeGen
(
args
));
return
passes
;
...
...
jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java
View file @
ebbe6db3
...
...
@@ -75,7 +75,7 @@ public class ConditionGen extends InsnGen {
}
else
if
(
op
==
IfOp
.
NE
)
{
// != true
code
.
add
(
'!'
);
boolean
wrap
=
isWrapNeeded
(
firstArg
);
boolean
wrap
=
is
Arg
WrapNeeded
(
firstArg
);
if
(
wrap
)
{
code
.
add
(
'('
);
}
...
...
@@ -88,9 +88,9 @@ public class ConditionGen extends InsnGen {
LOG
.
warn
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
"Unsupported boolean condition "
+
op
.
getSymbol
()));
}
addArg
(
code
,
firstArg
,
isWrapNeeded
(
firstArg
));
addArg
(
code
,
firstArg
,
is
Arg
WrapNeeded
(
firstArg
));
code
.
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
' '
);
addArg
(
code
,
secondArg
,
isWrapNeeded
(
secondArg
));
addArg
(
code
,
secondArg
,
is
Arg
WrapNeeded
(
secondArg
));
}
private
void
addNot
(
CodeWriter
code
,
IfCondition
condition
)
throws
CodegenException
{
...
...
@@ -110,15 +110,16 @@ public class ConditionGen extends InsnGen {
}
private
boolean
isWrapNeeded
(
IfCondition
condition
)
{
return
!
condition
.
isCompare
();
return
!
condition
.
isCompare
()
&&
condition
.
getMode
()
!=
IfCondition
.
Mode
.
NOT
;
}
private
static
boolean
isWrapNeeded
(
InsnArg
arg
)
{
private
static
boolean
is
Arg
WrapNeeded
(
InsnArg
arg
)
{
if
(!
arg
.
isInsnWrap
())
{
return
false
;
}
InsnNode
insn
=
((
InsnWrapArg
)
arg
).
getWrapInsn
();
if
(
insn
.
getType
()
==
InsnType
.
ARITH
)
{
InsnType
insnType
=
insn
.
getType
();
if
(
insnType
==
InsnType
.
ARITH
)
{
switch
(((
ArithNode
)
insn
).
getOp
())
{
case
ADD:
case
SUB:
...
...
@@ -127,8 +128,18 @@ public class ConditionGen extends InsnGen {
case
REM:
return
false
;
}
}
else
if
(
insn
.
getType
()
==
InsnType
.
INVOKE
)
{
return
false
;
}
else
{
switch
(
insnType
)
{
case
INVOKE:
case
SGET:
case
IGET:
case
AGET:
case
CONST:
case
ARRAY_LENGTH:
return
false
;
default
:
return
true
;
}
}
return
true
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
View file @
ebbe6db3
...
...
@@ -25,6 +25,9 @@ import jadx.core.dex.trycatch.SplitterBlockAttr;
*/
public
class
AType
<
T
extends
IAttribute
>
{
private
AType
()
{
}
public
static
final
AType
<
AttrList
<
JumpInfo
>>
JUMP
=
new
AType
<
AttrList
<
JumpInfo
>>();
public
static
final
AType
<
AttrList
<
LoopInfo
>>
LOOP
=
new
AType
<
AttrList
<
LoopInfo
>>();
...
...
jadx-core/src/main/java/jadx/core/dex/regions/IfCondition.java
View file @
ebbe6db3
...
...
@@ -69,13 +69,8 @@ public final class IfCondition {
IfCondition
n
=
new
IfCondition
(
a
);
n
.
addArg
(
b
);
return
n
;
}
else
if
(
b
.
getMode
()
==
mode
)
{
IfCondition
n
=
new
IfCondition
(
b
);
n
.
addArg
(
a
);
return
n
;
}
else
{
return
new
IfCondition
(
mode
,
Arrays
.
asList
(
a
,
b
));
}
return
new
IfCondition
(
mode
,
Arrays
.
asList
(
a
,
b
));
}
public
Mode
getMode
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/regions/IfInfo.java
View file @
ebbe6db3
...
...
@@ -2,41 +2,64 @@ package jadx.core.dex.regions;
import
jadx.core.dex.nodes.BlockNode
;
import
java.util.HashSet
;
import
java.util.Set
;
public
final
class
IfInfo
{
IfCondition
condition
;
BlockNode
ifnode
;
BlockNode
thenBlock
;
BlockNode
elseBlock
;
private
final
IfCondition
condition
;
private
final
Set
<
BlockNode
>
mergedBlocks
=
new
HashSet
<
BlockNode
>();
private
final
BlockNode
thenBlock
;
private
final
BlockNode
elseBlock
;
@Deprecated
private
BlockNode
ifBlock
;
public
IfCondition
getCondition
()
{
return
condition
;
public
IfInfo
(
IfCondition
condition
,
BlockNode
thenBlock
,
BlockNode
elseBlock
)
{
this
.
condition
=
condition
;
this
.
thenBlock
=
thenBlock
;
this
.
elseBlock
=
elseBlock
;
}
public
void
setCondition
(
IfCondition
condition
)
{
public
IfInfo
(
IfCondition
condition
,
IfInfo
info
)
{
this
.
condition
=
condition
;
this
.
thenBlock
=
info
.
getThenBlock
();
this
.
elseBlock
=
info
.
getElseBlock
();
this
.
mergedBlocks
.
addAll
(
info
.
getMergedBlocks
());
}
public
BlockNode
getIfnode
()
{
return
ifnode
;
public
static
IfInfo
invert
(
IfInfo
info
)
{
IfInfo
tmpIf
=
new
IfInfo
(
IfCondition
.
invert
(
info
.
getCondition
()),
info
.
getElseBlock
(),
info
.
getThenBlock
());
tmpIf
.
setIfBlock
(
info
.
getIfBlock
());
tmpIf
.
getMergedBlocks
().
addAll
(
info
.
getMergedBlocks
());
return
tmpIf
;
}
public
void
setIfnode
(
BlockNode
ifnode
)
{
this
.
ifnode
=
ifnode
;
public
IfCondition
getCondition
(
)
{
return
condition
;
}
public
BlockNode
getThenBlock
()
{
return
thenBlock
;
public
Set
<
BlockNode
>
getMergedBlocks
()
{
return
mergedBlocks
;
}
public
void
setThenBlock
(
BlockNode
thenBlock
)
{
this
.
thenBlock
=
thenBlock
;
public
BlockNode
getThenBlock
(
)
{
return
thenBlock
;
}
public
BlockNode
getElseBlock
()
{
return
elseBlock
;
}
public
void
setElseBlock
(
BlockNode
elseBlock
)
{
this
.
elseBlock
=
elseBlock
;
public
BlockNode
getIfBlock
()
{
return
ifBlock
;
}
public
void
setIfBlock
(
BlockNode
ifBlock
)
{
this
.
ifBlock
=
ifBlock
;
}
@Override
public
String
toString
()
{
return
"IfInfo: "
+
condition
+
", then: "
+
thenBlock
+
", else: "
+
elseBlock
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java
View file @
ebbe6db3
...
...
@@ -30,16 +30,14 @@ public class CheckRegions extends AbstractVisitor {
// check if all blocks included in regions
final
Set
<
BlockNode
>
blocksInRegions
=
new
HashSet
<
BlockNode
>();
IRegionVisitor
collectBlocks
=
new
AbstractRegionVisitor
()
{
DepthRegionTraversal
.
traverseAll
(
mth
,
new
AbstractRegionVisitor
()
{
@Override
public
void
processBlock
(
MethodNode
mth
,
IBlock
container
)
{
if
(
container
instanceof
BlockNode
)
{
blocksInRegions
.
add
((
BlockNode
)
container
);
}
}
};
DepthRegionTraversal
.
traverseAll
(
mth
,
collectBlocks
);
});
if
(
mth
.
getBasicBlocks
().
size
()
!=
blocksInRegions
.
size
())
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
if
(!
blocksInRegions
.
contains
(
block
)
...
...
@@ -52,19 +50,17 @@ public class CheckRegions extends AbstractVisitor {
}
// check loop conditions
IRegionVisitor
checkLoops
=
new
AbstractRegionVisitor
()
{
DepthRegionTraversal
.
traverseAll
(
mth
,
new
AbstractRegionVisitor
()
{
@Override
public
void
enterRegion
(
MethodNode
mth
,
IRegion
region
)
{
if
(
region
instanceof
LoopRegion
)
{
LoopRegion
loop
=
(
LoopRegion
)
region
;
BlockNode
loopHeader
=
loop
.
getHeader
();
BlockNode
loopHeader
=
((
LoopRegion
)
region
).
getHeader
();
if
(
loopHeader
!=
null
&&
loopHeader
.
getInstructions
().
size
()
!=
1
)
{
ErrorsCounter
.
methodError
(
mth
,
"Incorrect condition in loop: "
+
loopHeader
);
mth
.
add
(
AFlag
.
INCONSISTENT_CODE
);
}
}
}
};
DepthRegionTraversal
.
traverseAll
(
mth
,
checkLoops
);
});
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
core
.
dex
.
visitors
.
regions
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.regions.IfCondition
;
import
jadx.core.dex.regions.IfCondition.Mode
;
import
jadx.core.dex.regions.IfInfo
;
import
jadx.core.utils.BlockUtils
;
import
java.util.List
;
import
static
jadx
.
core
.
utils
.
BlockUtils
.
isPathExists
;
public
class
IfMakerHelper
{
private
IfMakerHelper
()
{
}
static
IfInfo
makeIfInfo
(
BlockNode
ifBlock
)
{
return
makeIfInfo
(
ifBlock
,
IfCondition
.
fromIfBlock
(
ifBlock
));
}
static
IfInfo
mergeNestedIfNodes
(
BlockNode
block
)
{
IfInfo
info
=
makeIfInfo
(
block
);
return
mergeNestedIfNodes
(
info
);
}
private
static
IfInfo
mergeNestedIfNodes
(
IfInfo
currentIf
)
{
BlockNode
curThen
=
currentIf
.
getThenBlock
();
BlockNode
curElse
=
currentIf
.
getElseBlock
();
if
(
curThen
==
curElse
)
{
return
null
;
}
boolean
followThenBranch
;
IfInfo
nextIf
=
getNextIf
(
currentIf
,
curThen
);
if
(
nextIf
!=
null
)
{
followThenBranch
=
true
;
}
else
{
nextIf
=
getNextIf
(
currentIf
,
curElse
);
if
(
nextIf
!=
null
)
{
followThenBranch
=
false
;
}
else
{
return
null
;
}
}
if
(
isInversionNeeded
(
currentIf
,
nextIf
))
{
// invert current node for match pattern
nextIf
=
IfInfo
.
invert
(
nextIf
);
}
if
(!
RegionMaker
.
isEqualPaths
(
curElse
,
nextIf
.
getElseBlock
())
&&
!
RegionMaker
.
isEqualPaths
(
curThen
,
nextIf
.
getThenBlock
()))
{
// complex condition, run additional checks
if
(
checkConditionBranches
(
curThen
,
curElse
)
||
checkConditionBranches
(
curElse
,
curThen
))
{
return
null
;
}
BlockNode
otherBranchBlock
=
followThenBranch
?
curElse
:
curThen
;
if
(!
isPathExists
(
nextIf
.
getIfBlock
(),
otherBranchBlock
))
{
return
null
;
}
if
(
isPathExists
(
nextIf
.
getThenBlock
(),
otherBranchBlock
)
&&
isPathExists
(
nextIf
.
getElseBlock
(),
otherBranchBlock
))
{
// both branches paths points to one block
return
null
;
}
// this is nested conditions with different mode (i.e (a && b) || c),
// search next condition for merge, get null if failed
IfInfo
tmpIf
=
mergeNestedIfNodes
(
nextIf
);
if
(
tmpIf
!=
null
)
{
nextIf
=
tmpIf
;
if
(
isInversionNeeded
(
currentIf
,
nextIf
))
{
nextIf
=
IfInfo
.
invert
(
nextIf
);
}
}
}
IfInfo
result
=
mergeIfInfo
(
currentIf
,
nextIf
,
followThenBranch
);
// search next nested if block
IfInfo
next
=
mergeNestedIfNodes
(
result
);
if
(
next
!=
null
)
{
return
next
;
}
return
result
;
}
private
static
boolean
isInversionNeeded
(
IfInfo
currentIf
,
IfInfo
nextIf
)
{
return
RegionMaker
.
isEqualPaths
(
currentIf
.
getElseBlock
(),
nextIf
.
getThenBlock
())
||
RegionMaker
.
isEqualPaths
(
currentIf
.
getThenBlock
(),
nextIf
.
getElseBlock
());
}
private
static
IfInfo
makeIfInfo
(
BlockNode
ifBlock
,
IfCondition
condition
)
{
IfNode
ifnode
=
(
IfNode
)
ifBlock
.
getInstructions
().
get
(
0
);
IfInfo
info
=
new
IfInfo
(
condition
,
ifnode
.
getThenBlock
(),
ifnode
.
getElseBlock
());
info
.
setIfBlock
(
ifBlock
);
info
.
getMergedBlocks
().
add
(
ifBlock
);
return
info
;
}
private
static
boolean
checkConditionBranches
(
BlockNode
from
,
BlockNode
to
)
{
return
from
.
getCleanSuccessors
().
size
()
==
1
&&
from
.
getCleanSuccessors
().
contains
(
to
);
}
private
static
IfInfo
mergeIfInfo
(
IfInfo
first
,
IfInfo
second
,
boolean
followThenBranch
)
{
Mode
mergeOperation
=
followThenBranch
?
Mode
.
AND
:
Mode
.
OR
;
BlockNode
otherPathBlock
=
followThenBranch
?
first
.
getElseBlock
()
:
first
.
getThenBlock
();
RegionMaker
.
skipSimplePath
(
otherPathBlock
);
first
.
getIfBlock
().
add
(
AFlag
.
SKIP
);
second
.
getIfBlock
().
add
(
AFlag
.
SKIP
);
IfCondition
condition
=
IfCondition
.
merge
(
mergeOperation
,
first
.
getCondition
(),
second
.
getCondition
());
IfInfo
result
=
new
IfInfo
(
condition
,
second
);
result
.
setIfBlock
(
first
.
getIfBlock
());
result
.
getMergedBlocks
().
addAll
(
first
.
getMergedBlocks
());
result
.
getMergedBlocks
().
addAll
(
second
.
getMergedBlocks
());
return
result
;
}
private
static
IfInfo
getNextIf
(
IfInfo
info
,
BlockNode
block
)
{
if
(!
canSelectNext
(
info
,
block
))
{
return
null
;
}
BlockNode
nestedIfBlock
=
getNextIfNode
(
block
);
if
(
nestedIfBlock
!=
null
)
{
return
makeIfInfo
(
nestedIfBlock
);
}
return
null
;
}
private
static
boolean
canSelectNext
(
IfInfo
info
,
BlockNode
block
)
{
if
(
block
.
getPredecessors
().
size
()
==
1
)
{
return
true
;
}
if
(
info
.
getMergedBlocks
().
containsAll
(
block
.
getPredecessors
()))
{
return
true
;
}
return
false
;
}
private
static
BlockNode
getNextIfNode
(
BlockNode
block
)
{
if
(
block
==
null
||
block
.
contains
(
AType
.
LOOP
)
||
block
.
contains
(
AFlag
.
SKIP
))
{
return
null
;
}
List
<
InsnNode
>
insns
=
block
.
getInstructions
();
if
(
insns
.
size
()
==
1
&&
insns
.
get
(
0
).
getType
()
==
InsnType
.
IF
)
{
return
block
;
}
// skip this block and search in successors chain
List
<
BlockNode
>
successors
=
block
.
getSuccessors
();
if
(
successors
.
size
()
!=
1
)
{
return
null
;
}
BlockNode
next
=
successors
.
get
(
0
);
if
(
next
.
getPredecessors
().
size
()
!=
1
)
{
return
null
;
}
boolean
pass
=
true
;
if
(!
insns
.
isEmpty
())
{
// check that all instructions can be inlined
for
(
InsnNode
insn
:
insns
)
{
RegisterArg
res
=
insn
.
getResult
();
if
(
res
==
null
)
{
pass
=
false
;
break
;
}
List
<
RegisterArg
>
useList
=
res
.
getSVar
().
getUseList
();
if
(
useList
.
size
()
!=
1
)
{
pass
=
false
;
break
;
}
InsnArg
arg
=
useList
.
get
(
0
);
InsnNode
usePlace
=
arg
.
getParentInsn
();
if
(!
BlockUtils
.
blockContains
(
block
,
usePlace
)
&&
!
BlockUtils
.
blockContains
(
next
,
usePlace
))
{
pass
=
false
;
break
;
}
}
}
if
(
pass
)
{
return
getNextIfNode
(
next
);
}
return
null
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfRegionVisitor.java
View file @
ebbe6db3
...
...
@@ -14,6 +14,8 @@ import jadx.core.utils.RegionUtils;
import
java.util.List
;
import
static
jadx
.
core
.
utils
.
RegionUtils
.
insnsCount
;
public
class
IfRegionVisitor
extends
AbstractVisitor
implements
IRegionVisitor
,
IRegionIterativeVisitor
{
@Override
...
...
@@ -60,10 +62,36 @@ public class IfRegionVisitor extends AbstractVisitor implements IRegionVisitor,
invertIfRegion
(
ifRegion
);
}
}
if
(
RegionUtils
.
isEmpty
(
ifRegion
.
getThenRegion
())
||
hasSimpleReturnBlock
(
ifRegion
.
getThenRegion
()))
{
IContainer
elseRegion
=
ifRegion
.
getElseRegion
();
if
(
elseRegion
==
null
||
RegionUtils
.
isEmpty
(
elseRegion
))
{
return
;
}
boolean
thenIsEmpty
=
RegionUtils
.
isEmpty
(
ifRegion
.
getThenRegion
());
if
(
thenIsEmpty
||
hasSimpleReturnBlock
(
ifRegion
.
getThenRegion
()))
{
invertIfRegion
(
ifRegion
);
}
if
(!
thenIsEmpty
)
{
// move 'if' from then to make 'else if' chain
if
(
isIfRegion
(
ifRegion
.
getThenRegion
())
&&
!
isIfRegion
(
elseRegion
))
{
invertIfRegion
(
ifRegion
);
}
}
}
private
static
boolean
isIfRegion
(
IContainer
container
)
{
if
(
container
instanceof
IfRegion
)
{
return
true
;
}
if
(
container
instanceof
IRegion
)
{
List
<
IContainer
>
subBlocks
=
((
IRegion
)
container
).
getSubBlocks
();
if
(
subBlocks
.
size
()
==
1
&&
subBlocks
.
get
(
0
)
instanceof
IfRegion
)
{
return
true
;
}
}
return
false
;
}
private
static
void
moveReturnToThenBlock
(
MethodNode
mth
,
IfRegion
ifRegion
)
{
...
...
@@ -95,7 +123,8 @@ public class IfRegionVisitor extends AbstractVisitor implements IRegionVisitor,
if
(
ifRegion
.
getElseRegion
()
!=
null
&&
!
ifRegion
.
contains
(
AFlag
.
ELSE_IF_CHAIN
)
&&
!
ifRegion
.
getElseRegion
().
contains
(
AFlag
.
ELSE_IF_CHAIN
)
&&
RegionUtils
.
hasExitBlock
(
ifRegion
.
getThenRegion
()))
{
&&
RegionUtils
.
hasExitBlock
(
ifRegion
.
getThenRegion
())
&&
insnsCount
(
ifRegion
.
getThenRegion
())
<
2
)
{
IRegion
parent
=
ifRegion
.
getParent
();
Region
newRegion
=
new
Region
(
parent
);
if
(
parent
.
replaceSubBlock
(
ifRegion
,
newRegion
))
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java
View file @
ebbe6db3
...
...
@@ -151,7 +151,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
aReg
.
setParent
(
newRegion
);
}
}
return
newRegion
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
ebbe6db3
This diff is collapsed.
Click to expand it.
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ReturnVisitor.java
View file @
ebbe6db3
...
...
@@ -43,7 +43,7 @@ public class ReturnVisitor extends AbstractVisitor {
if
(
insns
.
size
()
==
1
&&
blockNotInLoop
(
mth
,
block
)
&&
noTrailInstructions
(
block
))
{
insns
.
remove
(
insns
.
size
()
-
1
);
insns
.
remove
(
0
);
block
.
remove
(
AFlag
.
RETURN
);
}
}
...
...
@@ -96,7 +96,7 @@ public class ReturnVisitor extends AbstractVisitor {
/**
* Check if container not contains instructions,
* don't count one 'return' instruction (it will be removed later).
*/
*/
private
static
boolean
isEmpty
(
IContainer
container
)
{
if
(
container
instanceof
BlockNode
)
{
BlockNode
block
=
(
BlockNode
)
container
;
...
...
@@ -104,7 +104,7 @@ public class ReturnVisitor extends AbstractVisitor {
}
else
if
(
container
instanceof
IRegion
)
{
IRegion
region
=
(
IRegion
)
container
;
for
(
IContainer
block
:
region
.
getSubBlocks
())
{
if
(!
isEmpty
(
block
))
{
if
(!
isEmpty
(
block
))
{
return
false
;
}
}
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
View file @
ebbe6db3
...
...
@@ -203,9 +203,14 @@ public class BlockUtils {
}
public
static
boolean
isPathExists
(
BlockNode
start
,
BlockNode
end
)
{
if
(
start
==
end
||
end
.
isDominator
(
start
))
{
if
(
start
==
end
||
end
.
isDominator
(
start
)
||
start
.
getCleanSuccessors
().
contains
(
end
))
{
return
true
;
}
if
(
start
.
getPredecessors
().
contains
(
end
))
{
return
false
;
}
return
traverseSuccessorsUntil
(
start
,
end
,
new
BitSet
());
}
...
...
@@ -257,6 +262,12 @@ public class BlockUtils {
return
end
;
}
}
if
(
isPathExists
(
b1
,
b2
))
{
return
b2
;
}
if
(
isPathExists
(
b2
,
b1
))
{
return
b1
;
}
return
null
;
}
...
...
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
View file @
ebbe6db3
...
...
@@ -39,7 +39,7 @@ public class RegionUtils {
*/
public
static
boolean
hasExitBlock
(
IContainer
container
)
{
if
(
container
instanceof
BlockNode
)
{
return
((
BlockNode
)
container
).
getSuccessors
().
size
()
==
0
;
return
((
BlockNode
)
container
).
getSuccessors
().
isEmpty
()
;
}
else
if
(
container
instanceof
IRegion
)
{
List
<
IContainer
>
blocks
=
((
IRegion
)
container
).
getSubBlocks
();
return
!
blocks
.
isEmpty
()
...
...
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions10.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestConditions10
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
test
(
boolean
a
,
int
b
)
throws
Exception
{
if
(
a
||
b
>
2
)
{
b
++;
}
if
(!
a
||
(
b
>=
0
&&
b
<=
11
))
{
System
.
out
.
println
(
"1"
);
}
else
{
System
.
out
.
println
(
"2"
);
}
System
.
out
.
println
(
"3"
);
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
not
(
containsString
(
"return"
)));
assertThat
(
code
,
containsOne
(
"if (a || b > 2) {"
));
assertThat
(
code
,
containsOne
(
"b++;"
));
assertThat
(
code
,
containsOne
(
"if (!a || (b >= 0 && b <= 11)) {"
));
assertThat
(
code
,
containsOne
(
"System.out.println(\"1\");"
));
assertThat
(
code
,
containsOne
(
"} else {"
));
assertThat
(
code
,
containsOne
(
"System.out.println(\"2\");"
));
assertThat
(
code
,
containsOne
(
"System.out.println(\"3\");"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions11.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestConditions11
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
test
(
boolean
a
,
int
b
)
{
if
(
a
||
b
>
2
)
{
f
();
}
}
private
void
f
()
{
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsOne
(
"if (a || b > 2) {"
));
assertThat
(
code
,
containsOne
(
"f();"
));
assertThat
(
code
,
not
(
containsString
(
"return"
)));
assertThat
(
code
,
not
(
containsString
(
"else"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions12.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestConditions12
extends
InternalJadxTest
{
public
static
class
TestCls
{
static
boolean
autoStop
=
true
;
static
boolean
qualityReading
=
false
;
static
int
lastValidRaw
=
-
1
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
a
=
5
;
int
b
=
30
;
dataProcess
(
a
,
b
);
}
public
static
void
dataProcess
(
int
raw
,
int
quality
)
{
if
(
quality
>=
10
&&
raw
!=
0
)
{
System
.
out
.
println
(
"OK"
+
raw
);
qualityReading
=
false
;
}
else
if
(
raw
==
0
||
quality
<
6
||
!
qualityReading
)
{
System
.
out
.
println
(
"Not OK"
+
raw
);
}
else
{
System
.
out
.
println
(
"Quit OK"
+
raw
);
}
if
(
quality
<
30
)
{
int
timeLeft
=
30
-
quality
;
if
(
quality
>=
10
)
{
System
.
out
.
println
(
"Processing"
+
timeLeft
);
}
}
else
{
System
.
out
.
println
(
"Finish Processing"
);
if
(
raw
>
0
)
{
lastValidRaw
=
raw
;
}
}
if
(
quality
>=
30
&&
autoStop
)
{
System
.
out
.
println
(
"Finished"
);
}
if
(!
autoStop
&&
lastValidRaw
>
-
1
&&
quality
<
10
)
{
System
.
out
.
println
(
"Finished"
);
}
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsOne
(
"if (quality >= 10 && raw != 0) {"
));
assertThat
(
code
,
containsOne
(
"} else if (raw == 0 || quality < 6 || !qualityReading) {"
));
assertThat
(
code
,
containsOne
(
"if (quality < 30) {"
));
assertThat
(
code
,
containsOne
(
"if (quality >= 10) {"
));
assertThat
(
code
,
containsOne
(
"if (raw > 0) {"
));
assertThat
(
code
,
containsOne
(
"if (quality >= 30 && autoStop) {"
));
assertThat
(
code
,
containsOne
(
"if (!autoStop && lastValidRaw > -1 && quality < 10) {"
));
assertThat
(
code
,
not
(
containsString
(
"return"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions13.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestConditions13
extends
InternalJadxTest
{
public
static
class
TestCls
{
static
boolean
qualityReading
;
public
static
void
dataProcess
(
int
raw
,
int
quality
)
{
if
(
quality
>=
10
&&
raw
!=
0
)
{
System
.
out
.
println
(
"OK"
+
raw
);
qualityReading
=
false
;
}
else
if
(
raw
==
0
||
quality
<
6
||
!
qualityReading
)
{
System
.
out
.
println
(
"Not OK"
+
raw
);
}
else
{
System
.
out
.
println
(
"Quit OK"
+
raw
);
}
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsOne
(
"if (quality >= 10 && raw != 0) {"
));
assertThat
(
code
,
containsOne
(
"System.out.println(\"OK\" + raw);"
));
assertThat
(
code
,
containsOne
(
"qualityReading = false;"
));
assertThat
(
code
,
containsOne
(
"} else if (raw == 0 || quality < 6 || !qualityReading) {"
));
assertThat
(
code
,
not
(
containsString
(
"return"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions2.java
View file @
ebbe6db3
...
...
@@ -8,7 +8,6 @@ import org.junit.Test;
public
class
TestConditions2
extends
InternalJadxTest
{
public
static
class
TestCls
{
int
c
;
String
d
;
String
f
;
...
...
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions5.java
View file @
ebbe6db3
...
...
@@ -21,6 +21,18 @@ public class TestConditions5 extends InternalJadxTest {
throw
new
AssertionError
(
a1
+
" != "
+
a2
);
}
}
public
static
void
assertEquals2
(
Object
a1
,
Object
a2
)
{
if
(
a1
!=
null
)
{
if
(!
a1
.
equals
(
a2
))
{
throw
new
AssertionError
(
a1
+
" != "
+
a2
);
}
}
else
{
if
(
a2
!=
null
)
{
throw
new
AssertionError
(
a1
+
" != "
+
a2
);
}
}
}
}
@Test
...
...
jadx-core/src/test/java/jadx/tests/internal/conditions/TestConditions9.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestConditions9
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
test
(
boolean
a
,
int
b
)
throws
Exception
{
if
(!
a
||
(
b
>=
0
&&
b
<=
11
))
{
System
.
out
.
println
(
'1'
);
}
else
{
System
.
out
.
println
(
'2'
);
}
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsOne
(
"if (!a || (b >= 0 && b <= 11)) {"
));
assertThat
(
code
,
containsOne
(
"System.out.println('1');"
));
assertThat
(
code
,
containsOne
(
"} else {"
));
assertThat
(
code
,
containsOne
(
"System.out.println('2');"
));
assertThat
(
code
,
not
(
containsString
(
"return;"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/conditions/TestSimpleConditions.java
0 → 100644
View file @
ebbe6db3
package
jadx
.
tests
.
internal
.
conditions
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSimpleConditions
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
boolean
test1
(
boolean
[]
a
)
{
return
(
a
[
0
]
&&
a
[
1
]
&&
a
[
2
])
||
(
a
[
3
]
&&
a
[
4
]);
}
public
boolean
test2
(
boolean
[]
a
)
{
return
a
[
0
]
||
a
[
1
]
||
a
[
2
]
||
a
[
3
];
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"return (a[0] && a[1] && a[2]) || (a[3] && a[4]);"
));
assertThat
(
code
,
containsString
(
"return a[0] || a[1] || a[2] || a[3];"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/loops/TestLoopCondition2.java
View file @
ebbe6db3
...
...
@@ -5,7 +5,7 @@ import jadx.core.dex.nodes.ClassNode;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
jadx
.
tests
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestLoopCondition2
extends
InternalJadxTest
{
...
...
@@ -27,6 +27,9 @@ public class TestLoopCondition2 extends InternalJadxTest {
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"while (a && i < 10) {"
));
assertThat
(
code
,
containsOne
(
"int i = 0;"
));
assertThat
(
code
,
containsOne
(
"while (a && i < 10) {"
));
assertThat
(
code
,
containsOne
(
"i++;"
));
assertThat
(
code
,
containsOne
(
"return i;"
));
}
}
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