Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Quincy379
jadx
提交
5f3c8816
J
jadx
项目概览
Quincy379
/
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 搜索 >>
未验证
提交
5f3c8816
编写于
2月 26, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: allow zero skips for restore new filled array
上级
6016b902
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
69 addition
and
63 deletion
+69
-63
jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java
...ore/src/main/java/jadx/core/dex/visitors/ReSugarCode.java
+61
-48
jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java
...st/java/jadx/tests/integration/arrays/TestArrayFill3.java
+8
-15
未找到文件。
jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java
浏览文件 @
5f3c8816
package
jadx.core.dex.visitors
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.stream.Collectors
;
import
java.util.Map
;
import
java.util.SortedMap
;
import
java.util.TreeMap
;
import
org.jetbrains.annotations.Nullable
;
...
...
@@ -34,7 +34,6 @@ import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import
jadx.core.utils.InsnList
;
import
jadx.core.utils.InsnRemover
;
import
jadx.core.utils.InsnUtils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxException
;
@JadxVisitor
(
...
...
@@ -87,7 +86,7 @@ public class ReSugarCode extends AbstractVisitor {
}
switch
(
insn
.
getType
())
{
case
NEW_ARRAY:
return
processNewArray
(
mth
,
(
NewArrayNode
)
insn
,
instructions
,
i
,
remover
);
return
processNewArray
(
mth
,
(
NewArrayNode
)
insn
,
instructions
,
remover
);
case
SWITCH:
return
processEnumSwitch
(
mth
,
(
SwitchInsn
)
insn
);
...
...
@@ -100,8 +99,7 @@ public class ReSugarCode extends AbstractVisitor {
/**
* Replace new-array and sequence of array-put to new filled-array instruction.
*/
private
static
boolean
processNewArray
(
MethodNode
mth
,
NewArrayNode
newArrayInsn
,
List
<
InsnNode
>
instructions
,
int
i
,
InsnRemover
remover
)
{
private
static
boolean
processNewArray
(
MethodNode
mth
,
NewArrayNode
newArrayInsn
,
List
<
InsnNode
>
instructions
,
InsnRemover
remover
)
{
Object
arrayLenConst
=
InsnUtils
.
getConstValueByArg
(
mth
.
root
(),
newArrayInsn
.
getArg
(
0
));
if
(!(
arrayLenConst
instanceof
LiteralArg
))
{
return
false
;
...
...
@@ -110,50 +108,81 @@ public class ReSugarCode extends AbstractVisitor {
if
(
len
==
0
)
{
return
false
;
}
ArgType
arrType
=
newArrayInsn
.
getArrayType
();
ArgType
elemType
=
arrType
.
getArrayElement
();
boolean
allowMissingKeys
=
arrType
.
getArrayDimension
()
==
1
&&
elemType
.
isPrimitive
();
int
minLen
=
allowMissingKeys
?
len
/
2
:
len
;
RegisterArg
arrArg
=
newArrayInsn
.
getResult
();
List
<
RegisterArg
>
useList
=
arrArg
.
getSVar
().
getUseList
();
if
(
useList
.
size
()
<
l
en
)
{
if
(
useList
.
size
()
<
minL
en
)
{
return
false
;
}
List
<
InsnNode
>
arrPuts
=
useList
.
stream
()
.
map
(
InsnArg:
:
getParentInsn
)
.
filter
(
Objects:
:
nonNull
)
.
filter
(
insn
->
insn
.
getType
()
==
InsnType
.
APUT
)
.
sorted
(
Comparator
.
comparingLong
(
insn
->
{
Object
constVal
=
InsnUtils
.
getConstValueByArg
(
mth
.
root
(),
insn
.
getArg
(
1
));
if
(
constVal
instanceof
LiteralArg
)
{
return
((
LiteralArg
)
constVal
).
getLiteral
();
}
return
-
1
;
// bad value, put at top to fail fast next check
}))
.
collect
(
Collectors
.
toList
());
if
(
arrPuts
.
size
()
!=
len
)
{
return
false
;
// quick check if APUT is used
boolean
foundPut
=
false
;
for
(
RegisterArg
registerArg
:
useList
)
{
InsnNode
parentInsn
=
registerArg
.
getParentInsn
();
if
(
parentInsn
!=
null
&&
parentInsn
.
getType
()
==
InsnType
.
APUT
)
{
foundPut
=
true
;
break
;
}
}
// expect all puts to be in same block
if
(!
new
HashSet
<>(
instructions
).
containsAll
(
arrPuts
))
{
if
(!
foundPut
)
{
return
false
;
}
for
(
int
j
=
0
;
j
<
len
;
j
++)
{
InsnNode
insn
=
arrPuts
.
get
(
j
);
if
(!
checkPutInsn
(
mth
,
insn
,
arrArg
,
j
))
{
// collect put instructions sorted by array index
SortedMap
<
Long
,
InsnNode
>
arrPuts
=
new
TreeMap
<>();
for
(
RegisterArg
registerArg
:
useList
)
{
InsnNode
parentInsn
=
registerArg
.
getParentInsn
();
if
(
parentInsn
==
null
||
parentInsn
.
getType
()
!=
InsnType
.
APUT
)
{
continue
;
}
if
(!
arrArg
.
sameRegAndSVar
(
parentInsn
.
getArg
(
0
)))
{
return
false
;
}
Object
constVal
=
InsnUtils
.
getConstValueByArg
(
mth
.
root
(),
parentInsn
.
getArg
(
1
));
if
(!(
constVal
instanceof
LiteralArg
))
{
return
false
;
}
long
index
=
((
LiteralArg
)
constVal
).
getLiteral
();
if
(
index
>=
len
)
{
return
false
;
}
if
(
arrPuts
.
containsKey
(
index
))
{
// stop on index rewrite
break
;
}
arrPuts
.
put
(
index
,
parentInsn
);
}
if
(
arrPuts
.
size
()
<
minLen
)
{
return
false
;
}
// expect all puts to be in same block
if
(!
new
HashSet
<>(
instructions
).
containsAll
(
arrPuts
.
values
()))
{
return
false
;
}
// checks complete, apply
ArgType
arrType
=
newArrayInsn
.
getArrayType
();
InsnNode
filledArr
=
new
FilledNewArrayNode
(
arrType
.
getArrayElement
(),
len
);
InsnNode
filledArr
=
new
FilledNewArrayNode
(
elemType
,
len
);
filledArr
.
setResult
(
arrArg
.
duplicate
());
for
(
InsnNode
put
:
arrPuts
)
{
long
prevIndex
=
-
1
;
for
(
Map
.
Entry
<
Long
,
InsnNode
>
entry
:
arrPuts
.
entrySet
())
{
long
index
=
entry
.
getKey
();
if
(
index
!=
prevIndex
)
{
// use zero for missing keys
for
(
long
i
=
prevIndex
+
1
;
i
<
index
;
i
++)
{
filledArr
.
addArg
(
InsnArg
.
lit
(
0
,
elemType
));
}
}
InsnNode
put
=
entry
.
getValue
();
filledArr
.
addArg
(
replaceConstInArg
(
mth
,
put
.
getArg
(
2
)));
remover
.
addAndUnbind
(
put
);
prevIndex
=
index
;
}
remover
.
addAndUnbind
(
newArrayInsn
);
InsnNode
lastPut
=
Utils
.
last
(
arrPuts
);
InsnNode
lastPut
=
arrPuts
.
get
(
arrPuts
.
lastKey
()
);
int
replaceIndex
=
InsnList
.
getIndex
(
instructions
,
lastPut
);
instructions
.
set
(
replaceIndex
,
filledArr
);
return
true
;
...
...
@@ -172,22 +201,6 @@ public class ReSugarCode extends AbstractVisitor {
return
valueArg
.
duplicate
();
}
private
static
boolean
checkPutInsn
(
MethodNode
mth
,
InsnNode
insn
,
RegisterArg
arrArg
,
int
putIndex
)
{
if
(
insn
==
null
||
insn
.
getType
()
!=
InsnType
.
APUT
)
{
return
false
;
}
if
(!
arrArg
.
sameRegAndSVar
(
insn
.
getArg
(
0
)))
{
return
false
;
}
InsnArg
indexArg
=
insn
.
getArg
(
1
);
Object
value
=
InsnUtils
.
getConstValueByArg
(
mth
.
root
(),
indexArg
);
if
(
value
instanceof
LiteralArg
)
{
int
index
=
(
int
)
((
LiteralArg
)
value
).
getLiteral
();
return
index
==
putIndex
;
}
return
false
;
}
private
static
boolean
processEnumSwitch
(
MethodNode
mth
,
SwitchInsn
insn
)
{
InsnArg
arg
=
insn
.
getArg
(
0
);
if
(!
arg
.
isInsnWrap
())
{
...
...
jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFill3.java
浏览文件 @
5f3c8816
package
jadx.tests.integration.arrays
;
import
org.junit.jupiter.api.Test
;
import
jadx.NotYetImplemented
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
jadx.tests.api.extensions.profiles.TestProfile
;
import
jadx.tests.api.extensions.profiles.TestWithProfiles
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
jadx
.
tests
.
api
.
utils
.
assertj
.
JadxAssertions
.
assertThat
;
public
class
TestArrayFill3
extends
IntegrationTest
{
public
static
class
TestCls
{
public
byte
[]
test
(
int
a
)
{
public
byte
[]
test
()
{
return
new
byte
[]
{
0
,
1
,
2
};
}
}
@Test
@NotYetImplemented
@TestWithProfiles
({
TestProfile
.
ECJ_J8
,
TestProfile
.
ECJ_DX_J8
})
public
void
test
()
{
useEclipseCompiler
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"return new byte[]{0, 1, 2}"
));
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
()
.
containsOne
(
"return new byte[]{0, 1, 2}"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录