Skip to content

Commit f9097dc

Browse files
committed
fix: improve checking of access modifiers for methods
1 parent 9a8ec76 commit f9097dc

File tree

4 files changed

+101
-48
lines changed

4 files changed

+101
-48
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package jadx.core.dex.nodes.utils;
2+
3+
import jadx.core.dex.info.AccessInfo;
4+
import jadx.core.dex.nodes.ClassNode;
5+
import jadx.core.dex.nodes.FieldNode;
6+
import jadx.core.dex.nodes.ICodeNode;
7+
import jadx.core.dex.nodes.MethodNode;
8+
import jadx.core.dex.nodes.RootNode;
9+
import jadx.core.utils.exceptions.JadxRuntimeException;
10+
11+
class AccessCheckUtils {
12+
13+
private final RootNode root;
14+
15+
AccessCheckUtils(RootNode rootNode) {
16+
this.root = rootNode;
17+
}
18+
19+
boolean isAccessible(ICodeNode targetNode, ICodeNode callerNode) {
20+
ClassNode targetCls = getDeclaringClass(targetNode);
21+
ClassNode callerCls = getDeclaringClass(callerNode);
22+
23+
if (targetCls.equals(callerCls)) {
24+
return true;
25+
}
26+
27+
AccessInfo targetVisibility;
28+
if (targetNode == targetCls) {
29+
targetVisibility = targetNode.getAccessFlags().getVisibility();
30+
} else {
31+
AccessInfo targetClsVisibility = targetCls.getAccessFlags().getVisibility();
32+
AccessInfo targetNodeVisibility = targetNode.getAccessFlags().getVisibility();
33+
targetVisibility = targetClsVisibility.isVisibilityWeakerThan(targetNodeVisibility)
34+
? targetClsVisibility
35+
: targetNodeVisibility;
36+
}
37+
38+
if (targetVisibility.isPublic()) {
39+
return true;
40+
}
41+
42+
if (targetVisibility.isProtected()) {
43+
return isProtectedAccessible(targetCls, callerCls);
44+
}
45+
46+
if (targetVisibility.isPackagePrivate()) {
47+
return isPackagePrivateAccessible(targetCls, callerCls);
48+
}
49+
50+
if (targetVisibility.isPrivate()) {
51+
return isPrivateAccessible(targetCls, callerCls);
52+
}
53+
54+
throw new JadxRuntimeException(targetVisibility + " is not supported");
55+
}
56+
57+
private ClassNode getDeclaringClass(ICodeNode node) {
58+
if (node instanceof ClassNode) {
59+
return (ClassNode) node;
60+
} else if (node instanceof MethodNode) {
61+
return ((MethodNode) node).getParentClass();
62+
} else if (node instanceof FieldNode) {
63+
return ((FieldNode) node).getParentClass();
64+
} else {
65+
throw new JadxRuntimeException(node + " is not supported");
66+
}
67+
}
68+
69+
private boolean isProtectedAccessible(ClassNode cls, ClassNode callerCls) {
70+
return isPackagePrivateAccessible(cls, callerCls) || isSuperType(cls, callerCls);
71+
}
72+
73+
private boolean isPackagePrivateAccessible(ClassNode cls, ClassNode callerCls) {
74+
return cls.getPackageNode().equals(callerCls.getPackageNode());
75+
}
76+
77+
private boolean isPrivateAccessible(ClassNode cls, ClassNode callerCls) {
78+
return cls.getTopParentClass().equals(callerCls.getTopParentClass());
79+
}
80+
81+
private boolean isSuperType(ClassNode cls, ClassNode superCls) {
82+
return root.getClsp().getSuperTypes(cls.getRawName()).stream()
83+
.anyMatch(x -> x.equals(superCls.getRawName()));
84+
}
85+
}
Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,19 @@
11
package jadx.core.dex.nodes.utils;
22

3-
import jadx.core.dex.info.AccessInfo;
43
import jadx.core.dex.nodes.ClassNode;
54
import jadx.core.dex.nodes.RootNode;
6-
import jadx.core.utils.exceptions.JadxRuntimeException;
75

86
public class ClassUtils {
97

108
private final RootNode root;
9+
private final AccessCheckUtils accessCheckUtils;
1110

1211
public ClassUtils(RootNode rootNode) {
1312
this.root = rootNode;
13+
this.accessCheckUtils = new AccessCheckUtils(root);
1414
}
1515

1616
public boolean isAccessible(ClassNode cls, ClassNode callerCls) {
17-
if (cls.equals(callerCls)) {
18-
return true;
19-
}
20-
21-
final AccessInfo accessFlags = cls.getAccessFlags();
22-
if (accessFlags.isPublic()) {
23-
return true;
24-
}
25-
26-
if (accessFlags.isProtected()) {
27-
return isProtectedAccessible(cls, callerCls);
28-
}
29-
30-
if (accessFlags.isPackagePrivate()) {
31-
return isPackagePrivateAccessible(cls, callerCls);
32-
}
33-
34-
if (accessFlags.isPrivate()) {
35-
return isPrivateAccessible(cls, callerCls);
36-
}
37-
38-
throw new JadxRuntimeException(accessFlags + " is not supported");
39-
}
40-
41-
private boolean isProtectedAccessible(ClassNode cls, ClassNode callerCls) {
42-
return isPackagePrivateAccessible(cls, callerCls) || isSuperType(cls, callerCls);
43-
}
44-
45-
private boolean isPackagePrivateAccessible(ClassNode cls, ClassNode callerCls) {
46-
return cls.getPackageNode().equals(callerCls.getPackageNode());
47-
}
48-
49-
private boolean isPrivateAccessible(ClassNode cls, ClassNode callerCls) {
50-
return cls.getTopParentClass().equals(callerCls.getTopParentClass());
51-
}
52-
53-
private boolean isSuperType(ClassNode cls, ClassNode superCls) {
54-
return root.getClsp().getSuperTypes(cls.getRawName()).stream()
55-
.anyMatch(x -> x.equals(superCls.getRawName()));
17+
return accessCheckUtils.isAccessible(cls, callerCls);
5618
}
5719
}

jadx-core/src/main/java/jadx/core/dex/nodes/utils/MethodUtils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424

2525
public class MethodUtils {
2626
private final RootNode root;
27+
private final AccessCheckUtils accessCheckUtils;
2728

2829
public MethodUtils(RootNode rootNode) {
2930
this.root = rootNode;
31+
this.accessCheckUtils = new AccessCheckUtils(root);
3032
}
3133

3234
@Nullable
@@ -171,4 +173,8 @@ public ClassInfo getMethodOriginDeclClass(MethodNode mth) {
171173
}
172174
return mth.getMethodInfo().getDeclClass();
173175
}
176+
177+
public boolean isAccessible(MethodNode mth, MethodNode callerMth) {
178+
return accessCheckUtils.isAccessible(mth, callerMth);
179+
}
174180
}

jadx-core/src/main/java/jadx/core/dex/visitors/FixAccessModifiers.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import jadx.core.dex.nodes.MethodNode;
1616
import jadx.core.dex.nodes.RootNode;
1717
import jadx.core.dex.nodes.utils.ClassUtils;
18+
import jadx.core.dex.nodes.utils.MethodUtils;
1819
import jadx.core.utils.exceptions.JadxException;
1920

2021
@JadxVisitor(
@@ -25,12 +26,14 @@
2526
public class FixAccessModifiers extends AbstractVisitor {
2627

2728
private ClassUtils classUtils;
29+
private MethodUtils methodUtils;
2830

2931
private boolean respectAccessModifiers;
3032

3133
@Override
3234
public void init(RootNode root) {
3335
this.classUtils = root.getClassUtils();
36+
this.methodUtils = root.getMethodUtils();
3437
this.respectAccessModifiers = root.getArgs().isRespectBytecodeAccModifiers();
3538
}
3639

@@ -103,11 +106,12 @@ private int fixClassVisibility(ClassNode cls) {
103106
return -1;
104107
}
105108

106-
private static int fixMethodVisibility(MethodNode mth) {
109+
private int fixMethodVisibility(MethodNode mth) {
107110
AccessInfo accessFlags = mth.getAccessFlags();
108111
if (accessFlags.isPublic()) {
109112
return -1;
110113
}
114+
111115
MethodOverrideAttr overrideAttr = mth.get(AType.METHOD_OVERRIDE);
112116
if (overrideAttr != null && !overrideAttr.getOverrideList().isEmpty()) {
113117
// visibility can't be weaker
@@ -117,17 +121,13 @@ private static int fixMethodVisibility(MethodNode mth) {
117121
return parentAccInfo.getVisibility().rawValue();
118122
}
119123
}
120-
if (mth.getUseIn().isEmpty()) {
121-
return -1;
122-
}
123124

124-
ClassNode thisTopParentCls = mth.getParentClass().getTopParentClass();
125125
for (MethodNode useMth : mth.getUseIn()) {
126-
ClassNode useInTPCls = useMth.getParentClass().getTopParentClass();
127-
if (!useInTPCls.equals(thisTopParentCls)) {
126+
if (!methodUtils.isAccessible(mth, useMth)) {
128127
return AccessFlags.PUBLIC;
129128
}
130129
}
130+
131131
return -1;
132132
}
133133
}

0 commit comments

Comments
 (0)