Reflection analysis for Method.invoke(Object, Object[]) miss target when the second argument is generated by ArrayList.toArray(T[])
Opened this issue · 1 comments
Overall Description
A reproducible case "ListToArray.java" is shown in the following with the explanations for the bug. (The jdk8 compilable java source is in the attachment)
public class ListToArray {
public static void foo(String[] args) {}
public static void main(String[] args) throws Exception {
Method m = ListToArray.class.getMethod("foo", String[].class);
List<String> list = new ArrayList<>();
list.add("hello");
m.invoke(null, new Object[]{list.toArray(new String[0])});
}
}
In ListToArray.java, m.invoke(...) invokes ListToArray.foo method, according to jdk docs of API ArrayList.toArray(T[]), the argument of the invocation is a String array created by list.toArray(new String[0]) containing one String type element "hello".
In analyzing the above case, tai-e failed to analyze the invocation m.invoke, i.e. <ListToArray: void foo(java.lang.String[])> is not reachable
Current Behavior
Only <ListToArray: void main(java.lang.String[])> is in the dumped output/reachable-methods.txt
Expected Behavior
In the dumped output/reachable-methods.txt
<ListToArray: void main(java.lang.String[])>
<ListToArray: void foo(java.lang.String[])>
Tai-e Version
Tai-e Arguments
-cp /path/to/ListToArray.class
-m ListToArray
-java 8
-ap
-a pta=cs:ci
-a cg=dump-methods:true
-scope=REACHABLE
JDK Version
Corretto-17.0.4
System Environment
Windows 10
Additional Information
When analyzing m.invoke(null, new Object[]{list.toArray(new String[0])}); (tir in the following) Tai-e successfully resolved m($r2), i.e. <ListToArray: void foo(java.lang.String[])>, but failed to analyze the pts of $r4 elements and $r6 (pts is empty) because tai-e failed to analyze ArrayList.toArray(T[]), this may trigger typeMatcher.isUnmatched(invoke, target) -> true in methodInvoke method in ReflectiveActionModel.java.
[12@L12] $r4 = newarray java.lang.Object[%intconst0];
[13@L12] $r5 = newarray java.lang.String[%intconst1];
[14@L12] $r6 = invokeinterface $r3.<java.util.List: java.lang.Object[] toArray(java.lang.Object[])>($r5);
[15@L12] $r4[%intconst1] = $r6;
[16@L12] invokevirtual $r2.<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>(%nullconst, $r4);
Maybe a proper model to <java.util.List: java.lang.Object[] toArray(java.lang.Object[])> will solve the problem.
Additional Information (Modified)
My fault, I misunderstand how tai-e compute type info of an invoke, a proper model to <java.util.List: java.lang.Object[] toArray(java.lang.Object[])> only solves the empty pts problem of $r4 element and $r6.
When analyzing m.invoke(null, new Object[]{list.toArray(new String[0])}); (tir in the following) Tai-e successfully resolved m (i.e. $r2) as <ListToArray: void foo(java.lang.String[])>, but failed to analyze the pts of $r4 elements and $r6 (pts is empty) because tai-e failed to analyze ArrayList.toArray(T[]), this may trigger typeMatcher.isUnmatched(invoke, target) -> true in methodInvoke method in ReflectiveActionModel.java.
[12@L12] $r4 = newarray java.lang.Object[%intconst0];
[13@L12] $r5 = newarray java.lang.String[%intconst1];
[14@L12] $r6 = invokeinterface $r3.<java.util.List: java.lang.Object[] toArray(java.lang.Object[])>($r5);
[15@L12] $r4[%intconst1] = $r6;
[16@L12] invokevirtual $r2.<java.lang.reflect.Method: java.lang.Object invoke(java.lang.Object,java.lang.Object[])>(%nullconst, $r4);
Maybe a proper model to <java.util.List: java.lang.Object[] toArray(java.lang.Object[])> will solve the problem.