Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爽朗的琪琪
jadx
提交
e6b6b93c
J
jadx
项目概览
爽朗的琪琪
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
e6b6b93c
编写于
5月 31, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: improve blocks tree compare for finally extract (#1501)
上级
fcd58ae7
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
147 addition
and
34 deletion
+147
-34
jadx-core/src/main/java/jadx/core/Consts.java
jadx-core/src/main/java/jadx/core/Consts.java
+1
-0
jadx-core/src/main/java/jadx/core/dex/nodes/BlockNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/BlockNode.java
+4
-0
jadx-core/src/main/java/jadx/core/dex/visitors/finaly/FinallyExtractInfo.java
...ava/jadx/core/dex/visitors/finaly/FinallyExtractInfo.java
+17
-1
jadx-core/src/main/java/jadx/core/dex/visitors/finaly/MarkFinallyVisitor.java
...ava/jadx/core/dex/visitors/finaly/MarkFinallyVisitor.java
+68
-28
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
+5
-3
jadx-core/src/test/java/jadx/tests/api/extensions/profiles/TestProfile.java
.../java/jadx/tests/api/extensions/profiles/TestProfile.java
+7
-2
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally14.java
...adx/tests/integration/trycatch/TestTryCatchFinally14.java
+45
-0
未找到文件。
jadx-core/src/main/java/jadx/core/Consts.java
浏览文件 @
e6b6b93c
...
...
@@ -7,6 +7,7 @@ public class Consts {
public
static
final
boolean
DEBUG_TYPE_INFERENCE
=
false
;
public
static
final
boolean
DEBUG_OVERLOADED_CASTS
=
false
;
public
static
final
boolean
DEBUG_EXC_HANDLERS
=
false
;
public
static
final
boolean
DEBUG_FINALLY
=
false
;
public
static
final
String
CLASS_OBJECT
=
"java.lang.Object"
;
public
static
final
String
CLASS_STRING
=
"java.lang.String"
;
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/BlockNode.java
浏览文件 @
e6b6b93c
...
...
@@ -170,6 +170,10 @@ public final class BlockNode extends AttrNode implements IBlock, Comparable<Bloc
return
contains
(
AFlag
.
RETURN
);
}
public
boolean
isEmpty
()
{
return
instructions
.
isEmpty
();
}
@Override
public
int
hashCode
()
{
return
startOffset
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/finaly/FinallyExtractInfo.java
浏览文件 @
e6b6b93c
...
...
@@ -6,9 +6,12 @@ import java.util.List;
import
java.util.Set
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.utils.Utils
;
public
class
FinallyExtractInfo
{
private
final
MethodNode
mth
;
private
final
ExceptionHandler
finallyHandler
;
private
final
List
<
BlockNode
>
allHandlerBlocks
;
private
final
List
<
InsnsSlice
>
duplicateSlices
=
new
ArrayList
<>();
...
...
@@ -16,12 +19,17 @@ public class FinallyExtractInfo {
private
final
InsnsSlice
finallyInsnsSlice
=
new
InsnsSlice
();
private
final
BlockNode
startBlock
;
public
FinallyExtractInfo
(
ExceptionHandler
finallyHandler
,
BlockNode
startBlock
,
List
<
BlockNode
>
allHandlerBlocks
)
{
public
FinallyExtractInfo
(
MethodNode
mth
,
ExceptionHandler
finallyHandler
,
BlockNode
startBlock
,
List
<
BlockNode
>
allHandlerBlocks
)
{
this
.
mth
=
mth
;
this
.
finallyHandler
=
finallyHandler
;
this
.
startBlock
=
startBlock
;
this
.
allHandlerBlocks
=
allHandlerBlocks
;
}
public
MethodNode
getMth
()
{
return
mth
;
}
public
ExceptionHandler
getFinallyHandler
()
{
return
finallyHandler
;
}
...
...
@@ -45,4 +53,12 @@ public class FinallyExtractInfo {
public
BlockNode
getStartBlock
()
{
return
startBlock
;
}
@Override
public
String
toString
()
{
return
"FinallyExtractInfo{"
+
"\n finally:\n "
+
finallyInsnsSlice
+
"\n dups:\n "
+
Utils
.
listToString
(
duplicateSlices
,
"\n "
)
+
"\n}"
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/finaly/MarkFinallyVisitor.java
浏览文件 @
e6b6b93c
...
...
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.Consts
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.instructions.InsnType
;
...
...
@@ -38,6 +39,7 @@ import jadx.core.utils.Utils;
)
public
class
MarkFinallyVisitor
extends
AbstractVisitor
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
MarkFinallyVisitor
.
class
);
// private static final Logger LOG = LoggerFactory.getLogger(MarkFinallyVisitor.class);
@Override
public
void
visit
(
MethodNode
mth
)
{
...
...
@@ -60,7 +62,7 @@ public class MarkFinallyVisitor extends AbstractVisitor {
}
}
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Undo finally extract visitor, mth: {}"
,
mth
,
e
);
mth
.
addWarnComment
(
"Undo finally extract visitor"
,
e
);
undoFinallyVisitor
(
mth
);
}
}
...
...
@@ -100,20 +102,23 @@ public class MarkFinallyVisitor extends AbstractVisitor {
List
<
BlockNode
>
handlerBlocks
=
new
ArrayList
<>(
BlockUtils
.
collectBlocksDominatedByWithExcHandlers
(
mth
,
handlerBlock
,
handlerBlock
));
handlerBlocks
.
remove
(
handlerBlock
);
// exclude block with 'move-exception'
handlerBlocks
.
removeIf
(
b
->
BlockUtils
.
checkLastInsnType
(
b
,
InsnType
.
THROW
)
);
cutPathEnds
(
mth
,
handlerBlocks
);
if
(
handlerBlocks
.
isEmpty
()
||
BlockUtils
.
isAllBlocksEmpty
(
handlerBlocks
))
{
// remove empty catch
allHandler
.
getTryBlock
().
removeHandler
(
allHandler
);
return
true
;
}
BlockNode
startBlock
=
Utils
.
getOne
(
handlerBlock
.
getCleanSuccessors
());
FinallyExtractInfo
extractInfo
=
new
FinallyExtractInfo
(
allHandler
,
startBlock
,
handlerBlocks
);
FinallyExtractInfo
extractInfo
=
new
FinallyExtractInfo
(
mth
,
allHandler
,
startBlock
,
handlerBlocks
);
if
(
Consts
.
DEBUG_FINALLY
)
{
LOG
.
debug
(
"Finally info: handler=({}), start={}, blocks={}"
,
allHandler
,
startBlock
,
handlerBlocks
);
}
boolean
hasInnerBlocks
=
!
tryBlock
.
getInnerTryBlocks
().
isEmpty
();
List
<
ExceptionHandler
>
handlers
;
if
(
hasInnerBlocks
)
{
// collect handlers from this and all inner blocks
(intentionally not using recursive collect for
// now)
// collect handlers from this and all inner blocks
//
(intentionally not using recursive collect for
now)
handlers
=
new
ArrayList
<>(
tryBlock
.
getHandlers
());
for
(
TryCatchBlockAttr
innerTryBlock
:
tryBlock
.
getInnerTryBlocks
())
{
handlers
.
addAll
(
innerTryBlock
.
getHandlers
());
...
...
@@ -137,10 +142,12 @@ public class MarkFinallyVisitor extends AbstractVisitor {
}
}
}
if
(
Consts
.
DEBUG_FINALLY
)
{
LOG
.
debug
(
"Handlers slices:\n{}"
,
extractInfo
);
}
boolean
mergeInnerTryBlocks
;
int
duplicatesCount
=
extractInfo
.
getDuplicateSlices
().
size
();
boolean
fullTryBlock
=
duplicatesCount
==
(
handlers
.
size
()
-
1
);
if
(
fullTryBlock
)
{
if
(
duplicatesCount
==
(
handlers
.
size
()
-
1
))
{
// all collected handlers have duplicate block
mergeInnerTryBlocks
=
hasInnerBlocks
;
}
else
{
...
...
@@ -170,15 +177,24 @@ public class MarkFinallyVisitor extends AbstractVisitor {
if
(
upPath
.
size
()
<
handlerBlocks
.
size
())
{
continue
;
}
if
(
Consts
.
DEBUG_FINALLY
)
{
LOG
.
debug
(
"Checking dup path starts: {} from {}"
,
upPath
,
pred
);
}
for
(
BlockNode
block
:
upPath
)
{
if
(
searchDuplicateInsns
(
block
,
extractInfo
))
{
found
=
true
;
if
(
Consts
.
DEBUG_FINALLY
)
{
LOG
.
debug
(
"Found dup in: {} from {}"
,
block
,
pred
);
}
break
;
}
else
{
extractInfo
.
getFinallyInsnsSlice
().
resetIncomplete
();
}
}
}
if
(
Consts
.
DEBUG_FINALLY
)
{
LOG
.
debug
(
"Result slices:\n{}"
,
extractInfo
);
}
if
(!
found
)
{
return
false
;
}
...
...
@@ -204,6 +220,28 @@ public class MarkFinallyVisitor extends AbstractVisitor {
return
true
;
}
private
static
void
cutPathEnds
(
MethodNode
mth
,
List
<
BlockNode
>
handlerBlocks
)
{
List
<
BlockNode
>
throwBlocks
=
ListUtils
.
filter
(
handlerBlocks
,
b
->
BlockUtils
.
checkLastInsnType
(
b
,
InsnType
.
THROW
));
if
(
throwBlocks
.
size
()
!=
1
)
{
mth
.
addDebugComment
(
"Finally have unexpected throw blocks count: "
+
throwBlocks
.
size
()
+
", expect 1"
);
return
;
}
BlockNode
throwBlock
=
throwBlocks
.
get
(
0
);
handlerBlocks
.
remove
(
throwBlock
);
removeEmptyUpPath
(
handlerBlocks
,
throwBlock
);
}
private
static
void
removeEmptyUpPath
(
List
<
BlockNode
>
handlerBlocks
,
BlockNode
startBlock
)
{
for
(
BlockNode
pred
:
startBlock
.
getPredecessors
())
{
if
(
pred
.
isEmpty
())
{
if
(
handlerBlocks
.
remove
(
pred
)
&&
!
BlockUtils
.
isBackEdge
(
pred
,
startBlock
))
{
removeEmptyUpPath
(
handlerBlocks
,
pred
);
}
}
}
}
private
static
List
<
BlockNode
>
getPathStarts
(
MethodNode
mth
,
BlockNode
bottom
,
BlockNode
bottomFinallyBlock
)
{
Stream
<
BlockNode
>
preds
=
bottom
.
getPredecessors
().
stream
().
filter
(
b
->
b
!=
bottomFinallyBlock
);
if
(
bottom
==
mth
.
getExitBlock
())
{
...
...
@@ -219,9 +257,8 @@ public class MarkFinallyVisitor extends AbstractVisitor {
for
(
InsnsSlice
dupSlice
:
extractInfo
.
getDuplicateSlices
())
{
List
<
InsnNode
>
dupInsnsList
=
dupSlice
.
getInsnsList
();
if
(
dupInsnsList
.
size
()
!=
finallyInsnsList
.
size
())
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Incorrect finally slice size: {}, expected: {}"
,
dupSlice
,
finallySlice
);
}
extractInfo
.
getMth
().
addDebugComment
(
"Incorrect finally slice size: "
+
dupSlice
+
", expected: "
+
finallySlice
);
return
false
;
}
}
...
...
@@ -231,9 +268,8 @@ public class MarkFinallyVisitor extends AbstractVisitor {
List
<
InsnNode
>
insnsList
=
dupSlice
.
getInsnsList
();
InsnNode
dupInsn
=
insnsList
.
get
(
i
);
if
(
finallyInsn
.
getType
()
!=
dupInsn
.
getType
())
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Incorrect finally slice insn: {}, expected: {}"
,
dupInsn
,
finallyInsn
);
}
extractInfo
.
getMth
().
addDebugComment
(
"Incorrect finally slice insn: "
+
dupInsn
+
", expected: "
+
finallyInsn
);
return
false
;
}
}
...
...
@@ -342,24 +378,29 @@ public class MarkFinallyVisitor extends AbstractVisitor {
private
static
InsnsSlice
isStartBlock
(
BlockNode
dupBlock
,
BlockNode
finallyBlock
,
FinallyExtractInfo
extractInfo
)
{
List
<
InsnNode
>
dupInsns
=
dupBlock
.
getInstructions
();
List
<
InsnNode
>
finallyInsns
=
finallyBlock
.
getInstructions
();
if
(
dupInsns
.
size
()
<
finallyInsns
.
size
())
{
int
dupSize
=
dupInsns
.
size
();
int
finSize
=
finallyInsns
.
size
();
if
(
dupSize
<
finSize
)
{
return
null
;
}
int
startPos
=
dupInsns
.
size
()
-
finallyInsns
.
size
()
;
int
startPos
;
int
endPos
=
0
;
// fast check from end of block
if
(!
checkInsns
(
dupInsns
,
finallyInsns
,
startPos
))
{
// check from block start
if
(
checkInsns
(
dupInsns
,
finallyInsns
,
0
))
{
startPos
=
0
;
endPos
=
finallyInsns
.
size
();
}
else
{
if
(
dupSize
==
finSize
)
{
if
(!
checkInsns
(
dupInsns
,
finallyInsns
,
0
))
{
return
null
;
}
startPos
=
0
;
}
else
{
// dupSize > finSize
startPos
=
dupSize
-
finSize
;
// fast check from end of block
if
(!
checkInsns
(
dupInsns
,
finallyInsns
,
startPos
))
{
// search start insn
boolean
found
=
false
;
for
(
int
i
=
1
;
i
<
startPos
;
i
++)
{
if
(
checkInsns
(
dupInsns
,
finallyInsns
,
i
))
{
startPos
=
i
;
endPos
=
fin
allyInsns
.
size
()
+
i
;
endPos
=
fin
Size
+
i
;
found
=
true
;
break
;
}
...
...
@@ -379,7 +420,7 @@ public class MarkFinallyVisitor extends AbstractVisitor {
// both slices completed
complete
=
true
;
}
else
{
endIndex
=
dup
Insns
.
size
()
;
endIndex
=
dup
Size
;
complete
=
false
;
}
...
...
@@ -393,9 +434,8 @@ public class MarkFinallyVisitor extends AbstractVisitor {
if
(
finallySlice
.
isComplete
())
{
// compare slices
if
(
finallySlice
.
getInsnsList
().
size
()
!=
slice
.
getInsnsList
().
size
())
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Another duplicated slice has different insns count: {}, finally: {}"
,
slice
,
finallySlice
);
}
extractInfo
.
getMth
().
addDebugComment
(
"Another duplicated slice has different insns count: "
+
slice
+
", finally: "
+
finallySlice
);
return
null
;
}
// TODO: add additional slices checks
...
...
@@ -522,7 +562,7 @@ public class MarkFinallyVisitor extends AbstractVisitor {
DepthTraversal
.
visit
(
visitor
,
mth
);
}
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Undo finally extract failed, mth: {}"
,
mth
,
e
);
mth
.
addError
(
"Undo finally extract failed"
,
e
);
}
}
}
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
浏览文件 @
e6b6b93c
...
...
@@ -79,8 +79,6 @@ public abstract class IntegrationTest extends TestUtils {
private
static
final
String
TEST_DIRECTORY
=
"src/test/java"
;
private
static
final
String
TEST_DIRECTORY2
=
"jadx-core/"
+
TEST_DIRECTORY
;
private
static
final
String
OUT_DIR
=
"test-out-tmp"
;
private
static
final
String
DEFAULT_INPUT_PLUGIN
=
"dx"
;
/**
* Set 'TEST_INPUT_PLUGIN' env variable to use 'java' or 'dx' input in tests
...
...
@@ -132,7 +130,7 @@ public abstract class IntegrationTest extends TestUtils {
this
.
useJavaInput
=
null
;
args
=
new
JadxArgs
();
args
.
setOutDir
(
new
File
(
OUT_DIR
));
args
.
setOutDir
(
new
File
(
"test-out-tmp"
));
args
.
setShowInconsistentCode
(
true
);
args
.
setThreadsCount
(
1
);
args
.
setSkipResources
(
true
);
...
...
@@ -156,6 +154,10 @@ public abstract class IntegrationTest extends TestUtils {
}
}
public
void
setOutDirSuffix
(
String
suffix
)
{
args
.
setOutDir
(
new
File
(
"test-out-"
+
suffix
+
"-tmp"
));
}
public
String
getTestName
()
{
return
this
.
getClass
().
getSimpleName
();
}
...
...
jadx-core/src/test/java/jadx/tests/api/extensions/profiles/TestProfile.java
浏览文件 @
e6b6b93c
...
...
@@ -31,6 +31,10 @@ public enum TestProfile implements Consumer<IntegrationTest> {
test
.
useTargetJavaVersion
(
11
);
test
.
useJavaInput
();
}),
JAVA17
(
"java-17"
,
test
->
{
test
.
useTargetJavaVersion
(
17
);
test
.
useJavaInput
();
}),
ECJ_DX_J8
(
"ecj-dx-j8"
,
test
->
{
test
.
useEclipseCompiler
();
test
.
useTargetJavaVersion
(
8
);
...
...
@@ -52,8 +56,9 @@ public enum TestProfile implements Consumer<IntegrationTest> {
}
@Override
public
void
accept
(
IntegrationTest
integrationTest
)
{
this
.
setup
.
accept
(
integrationTest
);
public
void
accept
(
IntegrationTest
test
)
{
this
.
setup
.
accept
(
test
);
test
.
setOutDirSuffix
(
description
);
}
public
String
getDescription
()
{
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally14.java
0 → 100644
浏览文件 @
e6b6b93c
package
jadx.tests.integration.trycatch
;
import
jadx.tests.api.IntegrationTest
;
import
jadx.tests.api.extensions.profiles.TestProfile
;
import
jadx.tests.api.extensions.profiles.TestWithProfiles
;
import
static
jadx
.
tests
.
api
.
utils
.
assertj
.
JadxAssertions
.
assertThat
;
public
class
TestTryCatchFinally14
extends
IntegrationTest
{
@SuppressWarnings
(
"unused"
)
public
static
class
TestCls
{
private
TCls
t
;
public
void
test
()
{
try
{
if
(
t
!=
null
)
{
t
.
doSomething
();
}
}
finally
{
if
(
t
!=
null
)
{
t
.
doFinally
();
}
}
}
private
static
class
TCls
{
public
void
doSomething
()
{
}
public
void
doFinally
()
{
}
}
}
@TestWithProfiles
({
TestProfile
.
DX_J8
,
TestProfile
.
D8_J11
,
TestProfile
.
JAVA8
})
public
void
test
()
{
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
()
.
containsOne
(
".doSomething();"
)
.
containsOne
(
"} finally {"
)
.
containsOne
(
".doFinally();"
)
.
countString
(
2
,
"!= null) {"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录