Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflection analysis for Method.invoke(Object, Object[]) miss target when the second argument is generated by ArrayList.toArray(T[]) #100

Open
penguinfirst opened this issue Apr 8, 2024 · 1 comment

Comments

@penguinfirst
Copy link

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

ListToArray.zip

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

331589a

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.

@penguinfirst
Copy link
Author

penguinfirst commented Apr 9, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant