Skip to content

Commit 8d46ff0

Browse files
anddannmbenz89
authored andcommitted
add specialized methodreference to deal with polymorphic signature methods in java.lang.invoke.MethodHandle and java.lang.invoke.VarHandle
1 parent 6cb647e commit 8d46ff0

File tree

2 files changed

+113
-4
lines changed

2 files changed

+113
-4
lines changed

src/main/java/soot/Scene.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,14 +637,14 @@ private String defaultAndroidClassPath() {
637637

638638
return jarPath;
639639
}
640-
640+
641641
public static boolean isApk(String file) {
642642
// decide if a file is an APK by its magic number and whether it contains dex file.
643643
boolean r = false;
644644
// first check magic number
645645
File apk = new File(file);
646-
MagicNumberFileFilter apkFilter = new MagicNumberFileFilter(new byte[] {(byte) 0x50, (byte) 0x4B,
647-
(byte) 0x03, (byte) 0x04});
646+
MagicNumberFileFilter apkFilter
647+
= new MagicNumberFileFilter(new byte[] { (byte) 0x50, (byte) 0x4B, (byte) 0x03, (byte) 0x04 });
648648
if (!apkFilter.accept(apk)) {
649649
return r;
650650
}
@@ -672,7 +672,7 @@ public static boolean isApk(String file) {
672672
}
673673
}
674674
}
675-
675+
676676
return r;
677677
}
678678

@@ -1869,6 +1869,10 @@ public List<String> getPkgList() {
18691869
/** Create an unresolved reference to a method. */
18701870
public SootMethodRef makeMethodRef(SootClass declaringClass, String name, List<Type> parameterTypes, Type returnType,
18711871
boolean isStatic) {
1872+
if (declaringClass.getName().equals(SootMethodRefHandleImpl.METHODHANDLE_SIGNATURE)
1873+
|| declaringClass.getName().equals(SootMethodRefHandleImpl.VARHANDLE_SIGNATURE)) {
1874+
return new SootMethodRefHandleImpl(declaringClass, name, parameterTypes, returnType, isStatic);
1875+
}
18721876
return new SootMethodRefImpl(declaringClass, name, parameterTypes, returnType, isStatic);
18731877
}
18741878

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package soot;
2+
/*-
3+
* #%L
4+
* Soot - a J*va Optimization Framework
5+
* %%
6+
* Copyright (C) 2004 Ondrej Lhotak
7+
* %%
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as
10+
* published by the Free Software Foundation, either version 2.1 of the
11+
* License, or (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Lesser Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Lesser Public
19+
* License along with this program. If not, see
20+
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
21+
* #L%
22+
*/
23+
24+
import java.util.List;
25+
26+
import soot.tagkit.AnnotationTag;
27+
import soot.tagkit.Tag;
28+
import soot.tagkit.VisibilityAnnotationTag;
29+
30+
/**
31+
* Special class to treat the methods with polymorphic signatures in the classes {@link java.lang.invoke.MethodHandle} and
32+
* {@link java.lang.invoke.VarHandle}. As described in
33+
* https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.4.4 method references to the methods with a
34+
* polymorphic signature, which are the methods in `java.lang.invoke.MethodHandle` and `java.lang.invoke.VarHandle`, require
35+
* special treatment
36+
*
37+
* @author Andreas Dann created on 06.02.19
38+
*/
39+
public class SootMethodRefHandleImpl extends SootMethodRefImpl {
40+
41+
public static String METHODHANDLE_SIGNATURE = "java.lang.invoke.MethodHandle";
42+
43+
public static String VARHANDLE_SIGNATURE = "java.lang.invoke.VarHandle";
44+
45+
public static String POLYMORPHIC_SIGNATURE = "java/lang/invoke/MethodHandle$PolymorphicSignature";
46+
47+
/**
48+
* Constructor.
49+
*
50+
* @param declaringClass
51+
* the declaring class. Must not be {@code null}
52+
* @param name
53+
* the method name. Must not be {@code null}
54+
* @param parameterTypes
55+
* the types of parameters. May be {@code null}
56+
* @param returnType
57+
* the type of return value. Must not be {@code null}
58+
* @param isStatic
59+
* the static modifier value
60+
* @throws IllegalArgumentException
61+
* is thrown when {@code declaringClass}, or {@code name}, or {@code returnType} is null
62+
*/
63+
public SootMethodRefHandleImpl(SootClass declaringClass, String name, List<Type> parameterTypes, Type returnType,
64+
boolean isStatic) {
65+
super(declaringClass, name, parameterTypes, returnType, isStatic);
66+
}
67+
68+
@Override
69+
public SootMethod resolve() {
70+
71+
SootMethod method = getDeclaringClass().getMethodUnsafe(getName(), getParameterTypes(), getReturnType());
72+
if (method != null) {
73+
return method;
74+
}
75+
// no method with matching parametertypes or return types found
76+
// for polymorphic methods, we don't care about the return or parameter types. We just check if a method with the name
77+
// exists
78+
79+
method = getDeclaringClass().getMethodByName(getName());
80+
81+
if (method != null) {
82+
// the class declares a method with that name, check if the method is polymorphic
83+
Tag visibilityAnnotationTag = method.getTag("VisibilityAnnotationTag");
84+
if (visibilityAnnotationTag != null) {
85+
for (AnnotationTag annotation : ((VisibilityAnnotationTag) visibilityAnnotationTag).getAnnotations()) {
86+
// check the annotation's type
87+
if (annotation.getType().equals("L" + POLYMORPHIC_SIGNATURE + ";")) {
88+
// the method is polymorphic, add a fitting method to the MethodHandle or VarHandle class, as the JVM does on runtime
89+
return addPolyMorphicMethod(method);
90+
}
91+
}
92+
93+
}
94+
}
95+
96+
return null;
97+
}
98+
99+
private SootMethod addPolyMorphicMethod(SootMethod originalPolyMorphicMethod) {
100+
SootMethod newMethod
101+
= new SootMethod(getName(), getParameterTypes(), getReturnType(), originalPolyMorphicMethod.modifiers);
102+
getDeclaringClass().addMethod(newMethod);
103+
return newMethod;
104+
}
105+
}

0 commit comments

Comments
 (0)