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
02f9c25f
Commit
02f9c25f
authored
Jan 10, 2015
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: support fall through cases in switch
parent
7fb39881
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
302 additions
and
19 deletions
+302
-19
AFlag.java
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
+2
-0
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+87
-4
RegionMakerVisitor.java
...va/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
+53
-7
RegionStack.java
...main/java/jadx/core/dex/visitors/regions/RegionStack.java
+6
-0
RegionUtils.java
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
+18
-4
TestSwitch2.java
...est/java/jadx/tests/integration/switches/TestSwitch2.java
+5
-3
TestSwitchWithFallThroughCase.java
...s/integration/switches/TestSwitchWithFallThroughCase.java
+60
-0
TestSwitchWithFallThroughCase2.java
.../integration/switches/TestSwitchWithFallThroughCase2.java
+67
-0
TestSwitchWithTryCatch.java
...dx/tests/integration/switches/TestSwitchWithTryCatch.java
+4
-1
No files found.
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
View file @
02f9c25f
...
@@ -29,5 +29,7 @@ public enum AFlag {
...
@@ -29,5 +29,7 @@ public enum AFlag {
WRAPPED
,
WRAPPED
,
ARITH_ONEARG
,
ARITH_ONEARG
,
FALL_THROUGH
,
INCONSISTENT_CODE
,
// warning about incorrect decompilation
INCONSISTENT_CODE
,
// warning about incorrect decompilation
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
02f9c25f
...
@@ -32,6 +32,8 @@ import jadx.core.utils.exceptions.JadxOverflowException;
...
@@ -32,6 +32,8 @@ import jadx.core.utils.exceptions.JadxOverflowException;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.BitSet
;
import
java.util.BitSet
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.List
;
...
@@ -659,14 +661,47 @@ public class RegionMaker {
...
@@ -659,14 +661,47 @@ public class RegionMaker {
}
}
LoopInfo
loop
=
mth
.
getLoopForBlock
(
block
);
LoopInfo
loop
=
mth
.
getLoopForBlock
(
block
);
Map
<
BlockNode
,
BlockNode
>
fallThroughCases
=
new
LinkedHashMap
<
BlockNode
,
BlockNode
>();
BitSet
outs
=
new
BitSet
(
mth
.
getBasicBlocks
().
size
());
BitSet
outs
=
new
BitSet
(
mth
.
getBasicBlocks
().
size
());
outs
.
or
(
block
.
getDomFrontier
());
outs
.
or
(
block
.
getDomFrontier
());
for
(
BlockNode
s
:
block
.
getCleanSuccessors
())
{
for
(
BlockNode
s
:
block
.
getCleanSuccessors
())
{
outs
.
or
(
s
.
getDomFrontier
());
BitSet
df
=
s
.
getDomFrontier
();
// fall through case block
if
(
df
.
cardinality
()
>
1
)
{
if
(
df
.
cardinality
()
>
2
)
{
LOG
.
debug
(
"Unexpected case pattern, block: {}, mth: {}"
,
s
,
mth
);
}
else
{
BlockNode
first
=
mth
.
getBasicBlocks
().
get
(
df
.
nextSetBit
(
0
));
BlockNode
second
=
mth
.
getBasicBlocks
().
get
(
df
.
nextSetBit
(
first
.
getId
()
+
1
));
if
(
second
.
getDomFrontier
().
get
(
first
.
getId
()))
{
fallThroughCases
.
put
(
s
,
second
);
df
=
new
BitSet
(
df
.
size
());
df
.
set
(
first
.
getId
());
}
else
if
(
first
.
getDomFrontier
().
get
(
second
.
getId
()))
{
fallThroughCases
.
put
(
s
,
first
);
df
=
new
BitSet
(
df
.
size
());
df
.
set
(
second
.
getId
());
}
}
}
outs
.
or
(
df
);
}
}
stack
.
push
(
sw
);
stack
.
push
(
sw
);
stack
.
addExits
(
BlockUtils
.
bitSetToBlocks
(
mth
,
outs
));
stack
.
addExits
(
BlockUtils
.
bitSetToBlocks
(
mth
,
outs
));
// check cases order if fall through case exists
if
(!
fallThroughCases
.
isEmpty
())
{
if
(
isBadCasesOrder
(
blocksMap
,
fallThroughCases
))
{
LOG
.
debug
(
"Fixing incorrect switch cases order"
);
blocksMap
=
reOrderSwitchCases
(
blocksMap
,
fallThroughCases
);
if
(
isBadCasesOrder
(
blocksMap
,
fallThroughCases
))
{
LOG
.
error
(
"Can't fix incorrect switch cases order, method: {}"
,
mth
);
mth
.
add
(
AFlag
.
INCONSISTENT_CODE
);
}
}
}
// filter 'out' block
// filter 'out' block
if
(
outs
.
cardinality
()
>
1
)
{
if
(
outs
.
cardinality
()
>
1
)
{
// remove exception handlers
// remove exception handlers
...
@@ -677,6 +712,7 @@ public class RegionMaker {
...
@@ -677,6 +712,7 @@ public class RegionMaker {
List
<
BlockNode
>
blocks
=
mth
.
getBasicBlocks
();
List
<
BlockNode
>
blocks
=
mth
.
getBasicBlocks
();
for
(
int
i
=
outs
.
nextSetBit
(
0
);
i
>=
0
;
i
=
outs
.
nextSetBit
(
i
+
1
))
{
for
(
int
i
=
outs
.
nextSetBit
(
0
);
i
>=
0
;
i
=
outs
.
nextSetBit
(
i
+
1
))
{
BlockNode
b
=
blocks
.
get
(
i
);
BlockNode
b
=
blocks
.
get
(
i
);
outs
.
andNot
(
b
.
getDomFrontier
());
if
(
b
.
contains
(
AFlag
.
LOOP_START
))
{
if
(
b
.
contains
(
AFlag
.
LOOP_START
))
{
outs
.
clear
(
b
.
getId
());
outs
.
clear
(
b
.
getId
());
}
else
{
}
else
{
...
@@ -726,12 +762,21 @@ public class RegionMaker {
...
@@ -726,12 +762,21 @@ public class RegionMaker {
sw
.
setDefaultCase
(
makeRegion
(
defCase
,
stack
));
sw
.
setDefaultCase
(
makeRegion
(
defCase
,
stack
));
}
}
for
(
Entry
<
BlockNode
,
List
<
Object
>>
entry
:
blocksMap
.
entrySet
())
{
for
(
Entry
<
BlockNode
,
List
<
Object
>>
entry
:
blocksMap
.
entrySet
())
{
BlockNode
c
=
entry
.
getKey
();
BlockNode
c
aseBlock
=
entry
.
getKey
();
if
(
stack
.
containsExit
(
c
))
{
if
(
stack
.
containsExit
(
c
aseBlock
))
{
// empty case block
// empty case block
sw
.
addCase
(
entry
.
getValue
(),
new
Region
(
stack
.
peekRegion
()));
sw
.
addCase
(
entry
.
getValue
(),
new
Region
(
stack
.
peekRegion
()));
}
else
{
}
else
{
sw
.
addCase
(
entry
.
getValue
(),
makeRegion
(
c
,
stack
));
BlockNode
next
=
fallThroughCases
.
get
(
caseBlock
);
stack
.
addExit
(
next
);
Region
caseRegion
=
makeRegion
(
caseBlock
,
stack
);
stack
.
removeExit
(
next
);
if
(
next
!=
null
)
{
next
.
add
(
AFlag
.
FALL_THROUGH
);
caseRegion
.
add
(
AFlag
.
FALL_THROUGH
);
}
sw
.
addCase
(
entry
.
getValue
(),
caseRegion
);
// 'break' instruction will be inserted in RegionMakerVisitor.PostRegionVisitor
}
}
}
}
...
@@ -739,6 +784,44 @@ public class RegionMaker {
...
@@ -739,6 +784,44 @@ public class RegionMaker {
return
out
;
return
out
;
}
}
private
boolean
isBadCasesOrder
(
final
Map
<
BlockNode
,
List
<
Object
>>
blocksMap
,
final
Map
<
BlockNode
,
BlockNode
>
fallThroughCases
)
{
BlockNode
nextCaseBlock
=
null
;
for
(
BlockNode
caseBlock
:
blocksMap
.
keySet
())
{
if
(
nextCaseBlock
!=
null
&&
!
caseBlock
.
equals
(
nextCaseBlock
))
{
return
true
;
}
nextCaseBlock
=
fallThroughCases
.
get
(
caseBlock
);
}
return
nextCaseBlock
!=
null
;
}
private
Map
<
BlockNode
,
List
<
Object
>>
reOrderSwitchCases
(
Map
<
BlockNode
,
List
<
Object
>>
blocksMap
,
final
Map
<
BlockNode
,
BlockNode
>
fallThroughCases
)
{
List
<
BlockNode
>
list
=
new
ArrayList
<
BlockNode
>(
blocksMap
.
size
());
list
.
addAll
(
blocksMap
.
keySet
());
Collections
.
sort
(
list
,
new
Comparator
<
BlockNode
>()
{
@Override
public
int
compare
(
BlockNode
a
,
BlockNode
b
)
{
BlockNode
nextA
=
fallThroughCases
.
get
(
a
);
if
(
nextA
!=
null
)
{
if
(
b
.
equals
(
nextA
))
{
return
-
1
;
}
}
else
if
(
a
.
equals
(
fallThroughCases
.
get
(
b
)))
{
return
1
;
}
return
0
;
}
});
Map
<
BlockNode
,
List
<
Object
>>
newBlocksMap
=
new
LinkedHashMap
<
BlockNode
,
List
<
Object
>>(
blocksMap
.
size
());
for
(
BlockNode
key
:
list
)
{
newBlocksMap
.
put
(
key
,
blocksMap
.
get
(
key
));
}
return
newBlocksMap
;
}
private
static
void
insertContinueInSwitch
(
BlockNode
block
,
BlockNode
out
,
BlockNode
end
)
{
private
static
void
insertContinueInSwitch
(
BlockNode
block
,
BlockNode
out
,
BlockNode
end
)
{
int
endId
=
end
.
getId
();
int
endId
=
end
.
getId
();
for
(
BlockNode
s
:
block
.
getCleanSuccessors
())
{
for
(
BlockNode
s
:
block
.
getCleanSuccessors
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
View file @
02f9c25f
package
jadx
.
core
.
dex
.
visitors
.
regions
;
package
jadx
.
core
.
dex
.
visitors
.
regions
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.IBlock
;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.InsnContainer
;
import
jadx.core.dex.nodes.InsnContainer
;
...
@@ -16,7 +19,9 @@ import jadx.core.utils.RegionUtils;
...
@@ -16,7 +19,9 @@ import jadx.core.utils.RegionUtils;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
...
@@ -62,25 +67,66 @@ public class RegionMakerVisitor extends AbstractVisitor {
...
@@ -62,25 +67,66 @@ public class RegionMakerVisitor extends AbstractVisitor {
private
static
final
class
PostRegionVisitor
extends
AbstractRegionVisitor
{
private
static
final
class
PostRegionVisitor
extends
AbstractRegionVisitor
{
@Override
@Override
public
void
enter
Region
(
MethodNode
mth
,
IRegion
region
)
{
public
void
leave
Region
(
MethodNode
mth
,
IRegion
region
)
{
if
(
region
instanceof
LoopRegion
)
{
if
(
region
instanceof
LoopRegion
)
{
// merge conditions in loops
// merge conditions in loops
LoopRegion
loop
=
(
LoopRegion
)
region
;
LoopRegion
loop
=
(
LoopRegion
)
region
;
loop
.
mergePreCondition
();
loop
.
mergePreCondition
();
}
else
if
(
region
instanceof
SwitchRegion
)
{
}
else
if
(
region
instanceof
SwitchRegion
)
{
// insert 'break' in switch cases (run after try/catch insertion)
// insert 'break' in switch cases (run after try/catch insertion)
SwitchRegion
sw
=
(
SwitchRegion
)
region
;
processSwitch
(
mth
,
(
SwitchRegion
)
region
);
}
}
}
private
static
void
processSwitch
(
MethodNode
mth
,
SwitchRegion
sw
)
{
for
(
IContainer
c
:
sw
.
getBranches
())
{
for
(
IContainer
c
:
sw
.
getBranches
())
{
if
(
c
instanceof
Region
&&
!
RegionUtils
.
hasExitEdge
(
c
))
{
if
(!(
c
instanceof
Region
))
{
List
<
InsnNode
>
insns
=
new
ArrayList
<
InsnNode
>(
1
);
continue
;
insns
.
add
(
new
InsnNode
(
InsnType
.
BREAK
,
0
));
}
((
Region
)
c
).
add
(
new
InsnContainer
(
insns
));
Set
<
IBlock
>
blocks
=
new
HashSet
<
IBlock
>();
RegionUtils
.
getAllRegionBlocks
(
c
,
blocks
);
if
(
blocks
.
isEmpty
())
{
addBreakToContainer
((
Region
)
c
);
continue
;
}
for
(
IBlock
block
:
blocks
)
{
if
(!(
block
instanceof
BlockNode
))
{
continue
;
}
BlockNode
bn
=
(
BlockNode
)
block
;
for
(
BlockNode
s
:
bn
.
getCleanSuccessors
())
{
if
(!
blocks
.
contains
(
s
)
&&
!
bn
.
contains
(
AFlag
.
SKIP
)
&&
!
s
.
contains
(
AFlag
.
FALL_THROUGH
))
{
addBreak
(
mth
,
c
,
bn
);
break
;
}
}
}
}
}
}
}
}
}
}
private
static
void
addBreak
(
MethodNode
mth
,
IContainer
c
,
BlockNode
bn
)
{
IContainer
blockContainer
=
RegionUtils
.
getBlockContainer
(
c
,
bn
);
if
(
blockContainer
instanceof
Region
)
{
addBreakToContainer
((
Region
)
blockContainer
);
}
else
if
(
c
instanceof
Region
)
{
addBreakToContainer
((
Region
)
c
);
}
else
{
LOG
.
warn
(
"Can't insert break, container: {}, block: {}, mth: {}"
,
blockContainer
,
bn
,
mth
);
}
}
private
static
void
addBreakToContainer
(
Region
c
)
{
if
(
RegionUtils
.
hasExitEdge
(
c
))
{
return
;
}
List
<
InsnNode
>
insns
=
new
ArrayList
<
InsnNode
>(
1
);
insns
.
add
(
new
InsnNode
(
InsnType
.
BREAK
,
0
));
c
.
add
(
new
InsnContainer
(
insns
));
}
private
static
void
removeSynchronized
(
MethodNode
mth
)
{
private
static
void
removeSynchronized
(
MethodNode
mth
)
{
Region
startRegion
=
mth
.
getRegion
();
Region
startRegion
=
mth
.
getRegion
();
List
<
IContainer
>
subBlocks
=
startRegion
.
getSubBlocks
();
List
<
IContainer
>
subBlocks
=
startRegion
.
getSubBlocks
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionStack.java
View file @
02f9c25f
...
@@ -95,6 +95,12 @@ final class RegionStack {
...
@@ -95,6 +95,12 @@ final class RegionStack {
}
}
}
}
public
void
removeExit
(
BlockNode
exit
)
{
if
(
exit
!=
null
)
{
curState
.
exits
.
remove
(
exit
);
}
}
public
boolean
containsExit
(
BlockNode
exit
)
{
public
boolean
containsExit
(
BlockNode
exit
)
{
return
curState
.
exits
.
contains
(
exit
);
return
curState
.
exits
.
contains
(
exit
);
}
}
...
...
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
View file @
02f9c25f
...
@@ -8,8 +8,6 @@ import jadx.core.dex.nodes.IBranchRegion;
...
@@ -8,8 +8,6 @@ import jadx.core.dex.nodes.IBranchRegion;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.regions.SwitchRegion
;
import
jadx.core.dex.regions.conditions.IfRegion
;
import
jadx.core.dex.trycatch.CatchAttr
;
import
jadx.core.dex.trycatch.CatchAttr
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.trycatch.TryCatchBlock
;
import
jadx.core.dex.trycatch.TryCatchBlock
;
...
@@ -60,8 +58,7 @@ public class RegionUtils {
...
@@ -60,8 +58,7 @@ public class RegionUtils {
return
null
;
return
null
;
}
}
return
insnList
.
get
(
insnList
.
size
()
-
1
);
return
insnList
.
get
(
insnList
.
size
()
-
1
);
}
else
if
(
container
instanceof
IfRegion
}
else
if
(
container
instanceof
IBranchRegion
)
{
||
container
instanceof
SwitchRegion
)
{
return
null
;
return
null
;
}
else
if
(
container
instanceof
IRegion
)
{
}
else
if
(
container
instanceof
IRegion
)
{
IRegion
region
=
(
IRegion
)
container
;
IRegion
region
=
(
IRegion
)
container
;
...
@@ -235,6 +232,23 @@ public class RegionUtils {
...
@@ -235,6 +232,23 @@ public class RegionUtils {
return
true
;
return
true
;
}
}
public
static
IContainer
getBlockContainer
(
IContainer
container
,
BlockNode
block
)
{
if
(
container
instanceof
IBlock
)
{
return
container
==
block
?
container
:
null
;
}
else
if
(
container
instanceof
IRegion
)
{
IRegion
region
=
(
IRegion
)
container
;
for
(
IContainer
c
:
region
.
getSubBlocks
())
{
IContainer
res
=
getBlockContainer
(
c
,
block
);
if
(
res
!=
null
)
{
return
res
instanceof
IBlock
?
region
:
res
;
}
}
return
null
;
}
else
{
throw
new
JadxRuntimeException
(
"Unknown container type: "
+
container
.
getClass
());
}
}
public
static
boolean
isDominatedBy
(
BlockNode
dom
,
IContainer
cont
)
{
public
static
boolean
isDominatedBy
(
BlockNode
dom
,
IContainer
cont
)
{
if
(
dom
==
cont
)
{
if
(
dom
==
cont
)
{
return
true
;
return
true
;
...
...
jadx-core/src/test/java/jadx/tests/integration/switches/TestSwitch2.java
View file @
02f9c25f
...
@@ -60,9 +60,11 @@ public class TestSwitch2 extends IntegrationTest {
...
@@ -60,9 +60,11 @@ public class TestSwitch2 extends IntegrationTest {
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
countString
(
4
,
"break;"
));
// assertThat(code, countString(4, "break;"));
// assertThat(code, countString(2, "return;"));
// TODO: remove redundant returns
// TODO: remove redundant break and returns
// assertThat(code, countString(2, "return;"));
assertThat
(
code
,
countString
(
5
,
"break;"
));
assertThat
(
code
,
countString
(
4
,
"return;"
));
}
}
}
}
jadx-core/src/test/java/jadx/tests/integration/switches/TestSwitchWithFallThroughCase.java
0 → 100644
View file @
02f9c25f
package
jadx
.
tests
.
integration
.
switches
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSwitchWithFallThroughCase
extends
IntegrationTest
{
public
static
class
TestCls
{
public
String
test
(
int
a
,
boolean
b
,
boolean
c
)
{
String
str
=
""
;
switch
(
a
%
4
)
{
case
1
:
str
+=
">"
;
if
(
a
==
5
&&
b
)
{
if
(
c
)
{
str
+=
"1"
;
}
else
{
str
+=
"!c"
;
}
break
;
}
case
2
:
if
(
b
)
{
str
+=
"2"
;
}
break
;
case
3
:
break
;
default
:
str
+=
"default"
;
break
;
}
str
+=
";"
;
return
str
;
}
public
void
check
()
{
assertEquals
(
">1;"
,
test
(
5
,
true
,
true
));
assertEquals
(
">2;"
,
test
(
1
,
true
,
true
));
assertEquals
(
";"
,
test
(
3
,
true
,
true
));
assertEquals
(
"default;"
,
test
(
0
,
true
,
true
));
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"switch (a % 4) {"
));
assertThat
(
code
,
containsOne
(
"if (a == 5 && b) {"
));
assertThat
(
code
,
containsOne
(
"if (b) {"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/switches/TestSwitchWithFallThroughCase2.java
0 → 100644
View file @
02f9c25f
package
jadx
.
tests
.
integration
.
switches
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSwitchWithFallThroughCase2
extends
IntegrationTest
{
public
static
class
TestCls
{
public
String
test
(
int
a
,
boolean
b
,
boolean
c
)
{
String
str
=
""
;
if
(
a
>
0
)
{
switch
(
a
%
4
)
{
case
1
:
str
+=
">"
;
if
(
a
==
5
&&
b
)
{
if
(
c
)
{
str
+=
"1"
;
}
else
{
str
+=
"!c"
;
}
break
;
}
case
2
:
if
(
b
)
{
str
+=
"2"
;
}
break
;
case
3
:
break
;
default
:
str
+=
"default"
;
break
;
}
str
+=
"+"
;
}
if
(
b
&&
c
)
{
str
+=
"-"
;
}
return
str
;
}
public
void
check
()
{
assertEquals
(
">1+-"
,
test
(
5
,
true
,
true
));
assertEquals
(
">2+-"
,
test
(
1
,
true
,
true
));
assertEquals
(
"+-"
,
test
(
3
,
true
,
true
));
assertEquals
(
"default+-"
,
test
(
16
,
true
,
true
));
assertEquals
(
"-"
,
test
(-
1
,
true
,
true
));
}
}
@Test
public
void
test
()
{
setOutputCFG
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"switch (a % 4) {"
));
assertThat
(
code
,
containsOne
(
"if (a == 5 && b) {"
));
assertThat
(
code
,
containsOne
(
"if (b) {"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/switches/TestSwitchWithTryCatch.java
View file @
02f9c25f
...
@@ -62,7 +62,10 @@ public class TestSwitchWithTryCatch extends IntegrationTest {
...
@@ -62,7 +62,10 @@ public class TestSwitchWithTryCatch extends IntegrationTest {
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
countString
(
3
,
"break;"
));
//
assertThat(code, countString(3, "break;"));
assertThat
(
code
,
countString
(
4
,
"return;"
));
assertThat
(
code
,
countString
(
4
,
"return;"
));
// TODO: remove redundant break
assertThat
(
code
,
countString
(
4
,
"break;"
));
}
}
}
}
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