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
188bfd1a
Commit
188bfd1a
authored
Jun 01, 2018
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fix endless loop processing (#275)
parent
7b6825d8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
98 additions
and
87 deletions
+98
-87
TypeGen.java
jadx-core/src/main/java/jadx/core/codegen/TypeGen.java
+6
-2
ProcessVariables.java
...java/jadx/core/dex/visitors/regions/ProcessVariables.java
+7
-67
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+29
-14
DebugUtils.java
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
+1
-1
TestBreakInLoop2.java
...t/java/jadx/tests/integration/loops/TestBreakInLoop2.java
+2
-1
TestLoopConditionInvoke.java
...jadx/tests/integration/loops/TestLoopConditionInvoke.java
+1
-1
TestSequentialLoops.java
...ava/jadx/tests/integration/loops/TestSequentialLoops.java
+1
-1
TestSequentialLoops2.java
...va/jadx/tests/integration/loops/TestSequentialLoops2.java
+51
-0
No files found.
jadx-core/src/main/java/jadx/core/codegen/TypeGen.java
View file @
188bfd1a
...
@@ -4,6 +4,7 @@ import org.slf4j.Logger;
...
@@ -4,6 +4,7 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.JadxArgs
;
import
jadx.api.JadxArgs
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.PrimitiveType
;
import
jadx.core.dex.instructions.args.PrimitiveType
;
import
jadx.core.dex.nodes.IDexNode
;
import
jadx.core.dex.nodes.IDexNode
;
...
@@ -57,7 +58,11 @@ public class TypeGen {
...
@@ -57,7 +58,11 @@ public class TypeGen {
case
BOOLEAN:
case
BOOLEAN:
return
lit
==
0
?
"false"
:
"true"
;
return
lit
==
0
?
"false"
:
"true"
;
case
CHAR:
case
CHAR:
return
stringUtils
.
unescapeChar
((
char
)
lit
);
char
ch
=
(
char
)
lit
;
if
(!
NameMapper
.
isPrintableChar
(
ch
))
{
return
Integer
.
toString
(
ch
);
}
return
stringUtils
.
unescapeChar
(
ch
);
case
BYTE:
case
BYTE:
return
formatByte
((
byte
)
lit
);
return
formatByte
((
byte
)
lit
);
case
SHORT:
case
SHORT:
...
@@ -171,5 +176,4 @@ public class TypeGen {
...
@@ -171,5 +176,4 @@ public class TypeGen {
}
}
return
Float
.
toString
(
f
)
+
"f"
;
return
Float
.
toString
(
f
)
+
"f"
;
}
}
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java
View file @
188bfd1a
package
jadx
.
core
.
dex
.
visitors
.
regions
;
package
jadx
.
core
.
dex
.
visitors
.
regions
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedHashSet
;
...
@@ -10,9 +9,6 @@ import java.util.Map;
...
@@ -10,9 +9,6 @@ import java.util.Map;
import
java.util.Map.Entry
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.nodes.DeclareVariablesAttr
;
import
jadx.core.dex.attributes.nodes.DeclareVariablesAttr
;
...
@@ -21,7 +17,6 @@ import jadx.core.dex.instructions.args.ArgType;
...
@@ -21,7 +17,6 @@ import jadx.core.dex.instructions.args.ArgType;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.VarName
;
import
jadx.core.dex.instructions.args.VarName
;
import
jadx.core.dex.nodes.IBlock
;
import
jadx.core.dex.nodes.IBlock
;
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
;
...
@@ -34,7 +29,6 @@ import jadx.core.utils.RegionUtils;
...
@@ -34,7 +29,6 @@ import jadx.core.utils.RegionUtils;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxException
;
public
class
ProcessVariables
extends
AbstractVisitor
{
public
class
ProcessVariables
extends
AbstractVisitor
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ProcessVariables
.
class
);
private
static
class
Variable
{
private
static
class
Variable
{
private
final
int
regNum
;
private
final
int
regNum
;
...
@@ -213,16 +207,13 @@ public class ProcessVariables extends AbstractVisitor {
...
@@ -213,16 +207,13 @@ public class ProcessVariables extends AbstractVisitor {
return
;
return
;
}
}
Map
<
IContainer
,
Integer
>
regionsOrder
=
new
HashMap
<>();
calculateOrder
(
mth
.
getRegion
(),
regionsOrder
,
0
,
true
);
for
(
Iterator
<
Entry
<
Variable
,
Usage
>>
it
=
usageMap
.
entrySet
().
iterator
();
it
.
hasNext
();
)
{
for
(
Iterator
<
Entry
<
Variable
,
Usage
>>
it
=
usageMap
.
entrySet
().
iterator
();
it
.
hasNext
();
)
{
Entry
<
Variable
,
Usage
>
entry
=
it
.
next
();
Entry
<
Variable
,
Usage
>
entry
=
it
.
next
();
Usage
u
=
entry
.
getValue
();
Usage
u
=
entry
.
getValue
();
// check if variable can be declared at current assigns
// check if variable can be declared at current assigns
for
(
IRegion
assignRegion
:
u
.
getAssigns
())
{
for
(
IRegion
assignRegion
:
u
.
getAssigns
())
{
if
(
u
.
getArgRegion
()
==
assignRegion
if
(
u
.
getArgRegion
()
==
assignRegion
&&
canDeclareInRegion
(
u
,
assignRegion
,
regionsOrder
)
&&
canDeclareInRegion
(
u
,
assignRegion
)
&&
declareAtAssign
(
u
))
{
&&
declareAtAssign
(
u
))
{
it
.
remove
();
it
.
remove
();
break
;
break
;
...
@@ -258,7 +249,7 @@ public class ProcessVariables extends AbstractVisitor {
...
@@ -258,7 +249,7 @@ public class ProcessVariables extends AbstractVisitor {
IRegion
parent
=
region
;
IRegion
parent
=
region
;
boolean
declared
=
false
;
boolean
declared
=
false
;
while
(
parent
!=
null
)
{
while
(
parent
!=
null
)
{
if
(
canDeclareInRegion
(
u
,
region
,
regionsOrder
))
{
if
(
canDeclareInRegion
(
u
,
region
))
{
declareVar
(
region
,
u
.
getArg
());
declareVar
(
region
,
u
.
getArg
());
declared
=
true
;
declared
=
true
;
break
;
break
;
...
@@ -311,38 +302,7 @@ public class ProcessVariables extends AbstractVisitor {
...
@@ -311,38 +302,7 @@ public class ProcessVariables extends AbstractVisitor {
dv
.
addVar
(
arg
);
dv
.
addVar
(
arg
);
}
}
private
static
int
calculateOrder
(
IContainer
container
,
Map
<
IContainer
,
Integer
>
regionsOrder
,
int
id
,
boolean
inc
)
{
private
static
boolean
canDeclareInRegion
(
Usage
u
,
IRegion
region
)
{
if
(!(
container
instanceof
IRegion
))
{
return
id
;
}
IRegion
region
=
(
IRegion
)
container
;
Integer
previous
=
regionsOrder
.
put
(
region
,
id
);
if
(
previous
!=
null
)
{
return
id
;
}
for
(
IContainer
c
:
region
.
getSubBlocks
())
{
if
(
c
instanceof
IBranchRegion
)
{
// on branch set for all inner regions same order id
id
=
calculateOrder
(
c
,
regionsOrder
,
inc
?
id
+
1
:
id
,
false
);
}
else
{
List
<
IContainer
>
handlers
=
RegionUtils
.
getExcHandlersForRegion
(
c
);
if
(!
handlers
.
isEmpty
())
{
for
(
IContainer
handler
:
handlers
)
{
id
=
calculateOrder
(
handler
,
regionsOrder
,
inc
?
id
+
1
:
id
,
inc
);
}
}
id
=
calculateOrder
(
c
,
regionsOrder
,
inc
?
id
+
1
:
id
,
inc
);
}
}
return
id
;
}
private
static
boolean
canDeclareInRegion
(
Usage
u
,
IRegion
region
,
Map
<
IContainer
,
Integer
>
regionsOrder
)
{
Integer
pos
=
regionsOrder
.
get
(
region
);
if
(
pos
==
null
)
{
LOG
.
debug
(
"TODO: Not found order for region {} for {}"
,
region
,
u
);
return
false
;
}
// workaround for declare variables used in several loops
// workaround for declare variables used in several loops
if
(
region
instanceof
LoopRegion
)
{
if
(
region
instanceof
LoopRegion
)
{
for
(
IRegion
r
:
u
.
getAssigns
())
{
for
(
IRegion
r
:
u
.
getAssigns
())
{
...
@@ -355,32 +315,12 @@ public class ProcessVariables extends AbstractVisitor {
...
@@ -355,32 +315,12 @@ public class ProcessVariables extends AbstractVisitor {
if
(
region
.
contains
(
AFlag
.
ELSE_IF_CHAIN
))
{
if
(
region
.
contains
(
AFlag
.
ELSE_IF_CHAIN
))
{
return
false
;
return
false
;
}
}
return
isAllRegionsAfter
(
region
,
pos
,
u
.
getAssigns
(),
regionsOrder
)
// TODO: make index for faster search
&&
isAllRegionsAfter
(
region
,
pos
,
u
.
getUseRegions
(),
regionsOrder
);
return
isAllRegionsAfter
(
region
,
u
.
getAssigns
())
}
&&
isAllRegionsAfter
(
region
,
u
.
getUseRegions
());
private
static
boolean
isAllRegionsAfter
(
IRegion
region
,
int
pos
,
Set
<
IRegion
>
regions
,
Map
<
IContainer
,
Integer
>
regionsOrder
)
{
for
(
IRegion
r
:
regions
)
{
if
(
r
==
region
)
{
continue
;
}
Integer
rPos
=
regionsOrder
.
get
(
r
);
if
(
rPos
==
null
)
{
LOG
.
debug
(
"TODO: Not found order for region {} in {}"
,
r
,
regionsOrder
);
return
false
;
}
if
(
pos
>
rPos
)
{
return
false
;
}
if
(
pos
==
rPos
)
{
return
isAllRegionsAfterRecursive
(
region
,
regions
);
}
}
return
true
;
}
}
private
static
boolean
isAllRegionsAfter
Recursive
(
IRegion
region
,
Set
<
IRegion
>
others
)
{
private
static
boolean
isAllRegionsAfter
(
IRegion
region
,
Set
<
IRegion
>
others
)
{
for
(
IRegion
r
:
others
)
{
for
(
IRegion
r
:
others
)
{
if
(!
RegionUtils
.
isRegionContainsRegion
(
region
,
r
))
{
if
(!
RegionUtils
.
isRegionContainsRegion
(
region
,
r
))
{
return
false
;
return
false
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
188bfd1a
...
@@ -192,10 +192,9 @@ public class RegionMaker {
...
@@ -192,10 +192,9 @@ public class RegionMaker {
if
(
loopExit
!=
null
)
{
if
(
loopExit
!=
null
)
{
// add 'break' instruction before path cross between main loop exit and sub-exit
// add 'break' instruction before path cross between main loop exit and sub-exit
for
(
Edge
exitEdge
:
loop
.
getExitEdges
())
{
for
(
Edge
exitEdge
:
loop
.
getExitEdges
())
{
if
(
!
exitBlocks
.
contains
(
exitEdge
.
getSource
()))
{
if
(
exitBlocks
.
contains
(
exitEdge
.
getSource
()))
{
continue
;
insertBreak
(
stack
,
loopExit
,
exitEdge
)
;
}
}
insertBreak
(
stack
,
loopExit
,
exitEdge
);
}
}
}
}
}
}
...
@@ -207,7 +206,8 @@ public class RegionMaker {
...
@@ -207,7 +206,8 @@ public class RegionMaker {
loopStart
.
remove
(
AType
.
LOOP
);
loopStart
.
remove
(
AType
.
LOOP
);
loop
.
getEnd
().
add
(
AFlag
.
SKIP
);
loop
.
getEnd
().
add
(
AFlag
.
SKIP
);
stack
.
addExit
(
loop
.
getEnd
());
stack
.
addExit
(
loop
.
getEnd
());
loopRegion
.
setBody
(
makeRegion
(
loopStart
,
stack
));
Region
body
=
makeRegion
(
loopStart
,
stack
);
loopRegion
.
setBody
(
body
);
loopStart
.
addAttr
(
AType
.
LOOP
,
loop
);
loopStart
.
addAttr
(
AType
.
LOOP
,
loop
);
loop
.
getEnd
().
remove
(
AFlag
.
SKIP
);
loop
.
getEnd
().
remove
(
AFlag
.
SKIP
);
}
else
{
}
else
{
...
@@ -303,16 +303,31 @@ public class RegionMaker {
...
@@ -303,16 +303,31 @@ public class RegionMaker {
loopStart
.
remove
(
AType
.
LOOP
);
loopStart
.
remove
(
AType
.
LOOP
);
stack
.
push
(
loopRegion
);
stack
.
push
(
loopRegion
);
BlockNode
loopExi
t
=
null
;
BlockNode
ou
t
=
null
;
// insert 'break' for exits
// insert 'break' for exits
List
<
Edge
>
exitEdges
=
loop
.
getExitEdges
();
List
<
Edge
>
exitEdges
=
loop
.
getExitEdges
();
for
(
Edge
exitEdge
:
exitEdges
)
{
if
(
exitEdges
.
size
()
==
1
)
{
Edge
exitEdge
=
exitEdges
.
get
(
0
);
BlockNode
exit
=
exitEdge
.
getTarget
();
BlockNode
exit
=
exitEdge
.
getTarget
();
if
(
insertBreak
(
stack
,
exit
,
exitEdge
))
{
if
(
insertBreak
(
stack
,
exit
,
exitEdge
))
{
BlockNode
nextBlock
=
getNextBlock
(
exit
);
BlockNode
nextBlock
=
getNextBlock
(
exit
);
if
(
nextBlock
!=
null
)
{
if
(
nextBlock
!=
null
)
{
stack
.
addExit
(
nextBlock
);
stack
.
addExit
(
nextBlock
);
loopExit
=
nextBlock
;
out
=
nextBlock
;
}
}
}
else
{
for
(
Edge
exitEdge
:
exitEdges
)
{
BlockNode
exit
=
exitEdge
.
getTarget
();
List
<
BlockNode
>
blocks
=
BlockUtils
.
bitSetToBlocks
(
mth
,
exit
.
getDomFrontier
());
for
(
BlockNode
block
:
blocks
)
{
if
(
BlockUtils
.
isPathExists
(
exit
,
block
))
{
stack
.
addExit
(
block
);
insertBreak
(
stack
,
block
,
exitEdge
);
out
=
block
;
}
else
{
insertBreak
(
stack
,
exit
,
exitEdge
);
}
}
}
}
}
}
}
...
@@ -326,13 +341,13 @@ public class RegionMaker {
...
@@ -326,13 +341,13 @@ public class RegionMaker {
}
}
loopRegion
.
setBody
(
body
);
loopRegion
.
setBody
(
body
);
if
(
loopExi
t
==
null
)
{
if
(
ou
t
==
null
)
{
BlockNode
next
=
getNextBlock
(
loopEnd
);
BlockNode
next
=
getNextBlock
(
loopEnd
);
loopExi
t
=
RegionUtils
.
isRegionContainsBlock
(
body
,
next
)
?
null
:
next
;
ou
t
=
RegionUtils
.
isRegionContainsBlock
(
body
,
next
)
?
null
:
next
;
}
}
stack
.
pop
();
stack
.
pop
();
loopStart
.
addAttr
(
AType
.
LOOP
,
loop
);
loopStart
.
addAttr
(
AType
.
LOOP
,
loop
);
return
loopExi
t
;
return
ou
t
;
}
}
private
boolean
inExceptionHandlerBlocks
(
BlockNode
loopEnd
)
{
private
boolean
inExceptionHandlerBlocks
(
BlockNode
loopEnd
)
{
...
@@ -463,7 +478,7 @@ public class RegionMaker {
...
@@ -463,7 +478,7 @@ public class RegionMaker {
}
}
private
static
boolean
canInsertContinue
(
BlockNode
pred
,
List
<
BlockNode
>
predecessors
,
BlockNode
loopEnd
,
private
static
boolean
canInsertContinue
(
BlockNode
pred
,
List
<
BlockNode
>
predecessors
,
BlockNode
loopEnd
,
Set
<
BlockNode
>
loopExitNodes
)
{
Set
<
BlockNode
>
loopExitNodes
)
{
if
(!
pred
.
contains
(
AFlag
.
SYNTHETIC
)
if
(!
pred
.
contains
(
AFlag
.
SYNTHETIC
)
||
BlockUtils
.
checkLastInsnType
(
pred
,
InsnType
.
CONTINUE
))
{
||
BlockUtils
.
checkLastInsnType
(
pred
,
InsnType
.
CONTINUE
))
{
return
false
;
return
false
;
...
@@ -553,8 +568,8 @@ public class RegionMaker {
...
@@ -553,8 +568,8 @@ public class RegionMaker {
/**
/**
* Traverse from monitor-enter thru successors and collect blocks contains monitor-exit
* Traverse from monitor-enter thru successors and collect blocks contains monitor-exit
*/
*/
private
static
void
traverseMonitorExits
(
SynchronizedRegion
region
,
InsnArg
arg
,
BlockNode
block
,
private
static
void
traverseMonitorExits
(
SynchronizedRegion
region
,
InsnArg
arg
,
BlockNode
block
,
Set
<
BlockNode
>
exits
,
Set
<
BlockNode
>
exits
,
Set
<
BlockNode
>
visited
)
{
Set
<
BlockNode
>
visited
)
{
visited
.
add
(
block
);
visited
.
add
(
block
);
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_EXIT
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_EXIT
...
@@ -828,7 +843,7 @@ public class RegionMaker {
...
@@ -828,7 +843,7 @@ public class RegionMaker {
}
}
private
boolean
isBadCasesOrder
(
Map
<
BlockNode
,
List
<
Object
>>
blocksMap
,
private
boolean
isBadCasesOrder
(
Map
<
BlockNode
,
List
<
Object
>>
blocksMap
,
Map
<
BlockNode
,
BlockNode
>
fallThroughCases
)
{
Map
<
BlockNode
,
BlockNode
>
fallThroughCases
)
{
BlockNode
nextCaseBlock
=
null
;
BlockNode
nextCaseBlock
=
null
;
for
(
BlockNode
caseBlock
:
blocksMap
.
keySet
())
{
for
(
BlockNode
caseBlock
:
blocksMap
.
keySet
())
{
if
(
nextCaseBlock
!=
null
&&
!
caseBlock
.
equals
(
nextCaseBlock
))
{
if
(
nextCaseBlock
!=
null
&&
!
caseBlock
.
equals
(
nextCaseBlock
))
{
...
...
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
View file @
188bfd1a
...
@@ -99,7 +99,7 @@ public class DebugUtils {
...
@@ -99,7 +99,7 @@ public class DebugUtils {
CodeWriter
code
=
new
CodeWriter
();
CodeWriter
code
=
new
CodeWriter
();
ig
.
makeInsn
(
insn
,
code
);
ig
.
makeInsn
(
insn
,
code
);
String
insnStr
=
code
.
toString
().
substring
(
CodeWriter
.
NL
.
length
());
String
insnStr
=
code
.
toString
().
substring
(
CodeWriter
.
NL
.
length
());
LOG
.
debug
(
"{}> {}
"
,
indent
,
insnStr
);
LOG
.
debug
(
"{}> {}
\t{}"
,
indent
,
insnStr
,
insn
.
getAttributesString
()
);
}
catch
(
CodegenException
e
)
{
}
catch
(
CodegenException
e
)
{
LOG
.
debug
(
"{}>!! {}"
,
indent
,
insn
);
LOG
.
debug
(
"{}>!! {}"
,
indent
,
insn
);
}
}
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestBreakInLoop2.java
View file @
188bfd1a
...
@@ -9,6 +9,7 @@ import jadx.tests.api.IntegrationTest;
...
@@ -9,6 +9,7 @@ import jadx.tests.api.IntegrationTest;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
anyOf
;
public
class
TestBreakInLoop2
extends
IntegrationTest
{
public
class
TestBreakInLoop2
extends
IntegrationTest
{
...
@@ -43,7 +44,7 @@ public class TestBreakInLoop2 extends IntegrationTest {
...
@@ -43,7 +44,7 @@ public class TestBreakInLoop2 extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"while (true) {"
));
assertThat
(
code
,
containsOne
(
"while (true) {"
));
assertThat
(
code
,
containsOne
(
"break;"
));
assertThat
(
code
,
anyOf
(
containsOne
(
"break;"
),
containsOne
(
"return;"
)
));
assertThat
(
code
,
containsOne
(
"throw ex;"
));
assertThat
(
code
,
containsOne
(
"throw ex;"
));
assertThat
(
code
,
containsOne
(
"data.clear();"
));
assertThat
(
code
,
containsOne
(
"data.clear();"
));
assertThat
(
code
,
containsOne
(
"Thread.sleep(100);"
));
assertThat
(
code
,
containsOne
(
"Thread.sleep(100);"
));
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestLoopConditionInvoke.java
View file @
188bfd1a
...
@@ -37,7 +37,7 @@ public class TestLoopConditionInvoke extends IntegrationTest {
...
@@ -37,7 +37,7 @@ public class TestLoopConditionInvoke extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"do {"
));
assertThat
(
code
,
containsOne
(
"do {"
));
assertThat
(
code
,
containsOne
(
"if (ch ==
'\\u0000'
) {"
));
assertThat
(
code
,
containsOne
(
"if (ch ==
0
) {"
));
assertThat
(
code
,
containsOne
(
"this.pos = startPos;"
));
assertThat
(
code
,
containsOne
(
"this.pos = startPos;"
));
assertThat
(
code
,
containsOne
(
"return false;"
));
assertThat
(
code
,
containsOne
(
"return false;"
));
assertThat
(
code
,
containsOne
(
"} while (ch != lastChar);"
));
assertThat
(
code
,
containsOne
(
"} while (ch != lastChar);"
));
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestSequentialLoops.java
View file @
188bfd1a
...
@@ -14,7 +14,7 @@ import static org.junit.Assert.assertThat;
...
@@ -14,7 +14,7 @@ import static org.junit.Assert.assertThat;
public
class
TestSequentialLoops
extends
IntegrationTest
{
public
class
TestSequentialLoops
extends
IntegrationTest
{
public
static
class
TestCls
{
public
static
class
TestCls
{
public
int
test
7
(
int
a
,
int
b
)
{
public
int
test
(
int
a
,
int
b
)
{
int
c
=
b
;
int
c
=
b
;
int
z
;
int
z
;
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestSequentialLoops2.java
0 → 100644
View file @
188bfd1a
package
jadx
.
tests
.
integration
.
loops
;
import
org.junit.Test
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
countString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSequentialLoops2
extends
IntegrationTest
{
public
static
class
TestCls
{
private
static
char
[]
lowercases
=
new
char
[]{
'a'
};
public
static
String
asciiToLowerCase
(
String
s
)
{
char
[]
c
=
null
;
int
i
=
s
.
length
();
while
(
i
--
>
0
)
{
char
c1
=
s
.
charAt
(
i
);
if
(
c1
<=
127
)
{
char
c2
=
lowercases
[
c1
];
if
(
c1
!=
c2
)
{
c
=
s
.
toCharArray
();
c
[
i
]
=
c2
;
break
;
}
}
}
while
(
i
--
>
0
)
{
if
(
c
[
i
]
<=
127
)
{
c
[
i
]
=
lowercases
[
c
[
i
]];
}
}
return
c
==
null
?
s
:
new
String
(
c
);
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
countString
(
2
,
"while ("
));
assertThat
(
code
,
containsString
(
"break;"
));
assertThat
(
code
,
containsOne
(
"return c"
));
assertThat
(
code
,
countString
(
2
,
"<= 127"
));
}
}
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