soot-oss / soot

Soot - A Java optimization framework
GNU Lesser General Public License v2.1
2.84k stars 708 forks source link

Soot generates redundant statements #2045

Open Momo-Not-Emo opened 5 months ago

Momo-Not-Emo commented 5 months ago

Describe the bug Soot generates redundant Jimple statements while SootUp does not

Input file https://github.com/soot-oss/SootUp/blob/develop/shared-test-resources/miniTestSuite/java6/binary/Reflection.class https://github.com/soot-oss/SootUp/blob/develop/shared-test-resources/miniTestSuite/java6/source/Reflection.java

To reproduce soot version (commit id): 0e7e27d457e036ade112d91e1d97cf6a764eb0a9

Copy the input file to test resource directory, and run the following code

    public void loadClasses(String first, String... more) {
        G.reset();
        Path cp = Paths.get(first, more);
        G.reset();
        Options.v().set_prepend_classpath(true);
        Options.v().set_process_dir(Collections.singletonList(cp.toFile().getAbsolutePath()));
        Options.v().set_src_prec(Options.src_prec_class);
        Options.v().set_output_format(Options.output_format_jimple);
        Options.v().set_allow_phantom_refs(true);
        Options.v().set_ignore_resolving_levels(true);
        Scene.v().loadNecessaryClasses();
    }

    public static void main(String[] args) {
        loadClasses(RESOURCE_PATH);
        SootMethod method = Scene.v().getMethod("<Autoboxing: void autoboxing()>");
        Body body = method.retrieveActiveBody();
        List<String> actualStmts = bodyStmtsAsStrings(body);

        for (String item : actualStmts) {
            System.out.println(item);
        }
        System.out.println();
}

Its output is as below, where the assignments of r1, r11, r10 are redundant (only one assignment is generated in SootUp)

r9 := @this: Reflection
$r0 = new Reflection
specialinvoke $r0.<Reflection: void <init>()>()
r1 = class "LReflection;"
r11 = class "LReflection;"
r10 = class "LReflection;"
$r2 = <java.lang.System: java.io.PrintStream out>
virtualinvoke $r2.<java.io.PrintStream: void println(java.lang.Object)>(class "LReflection;")
$r3 = newarray (java.lang.Class)[0]
$r4 = virtualinvoke r10.<java.lang.Class: java.lang.reflect.Constructor getConstructor(java.lang.Class[])>($r3)
$r5 = <java.lang.System: java.io.PrintStream out>
$r6 = virtualinvoke $r4.<java.lang.reflect.Constructor: java.lang.String getName()>()
virtualinvoke $r5.<java.io.PrintStream: void println(java.lang.String)>($r6)
$r7 = <java.lang.System: java.io.PrintStream out>
$r8 = virtualinvoke r11.<java.lang.Class: java.lang.reflect.Method[] getMethods()>()
$i0 = lengthof $r8
virtualinvoke $r7.<java.io.PrintStream: void println(int)>($i0)
return

Expected behavior

Remove the redundant statements of class "LReflection;".

The expected output should be like:

r9 := @this: Reflection
$r0 = new Reflection
specialinvoke $r0.<Reflection: void <init>()>()
r1 = class "LReflection;"
$r2 = <java.lang.System: java.io.PrintStream out>
virtualinvoke $r2.<java.io.PrintStream: void println(java.lang.Object)>(r1)
$r3 = newarray (java.lang.Class)[0]
$r4 = virtualinvoke r1.<java.lang.Class: java.lang.reflect.Constructor getConstructor(java.lang.Class[])>($r3)
$r5 = <java.lang.System: java.io.PrintStream out>
$r6 = virtualinvoke $r4.<java.lang.reflect.Constructor: java.lang.String getName()>()
virtualinvoke $r5.<java.io.PrintStream: void println(java.lang.String)>($r6)
$r7 = <java.lang.System: java.io.PrintStream out>
$r8 = virtualinvoke r1.<java.lang.Class: java.lang.reflect.Method[] getMethods()>()
$i0 = lengthof $r8
virtualinvoke $r7.<java.io.PrintStream: void println(int)>($i0)
return
Momo-Not-Emo commented 5 months ago

Related discussion https://github.com/soot-oss/SootUp/pull/472#issuecomment-1925701161