leibnitz27 / cfr

This is the public repository for the CFR Java decompiler
https://www.benf.org/other/cfr
MIT License
2k stars 258 forks source link

CFR performs problematic code inlining that reverses the execution order of the code #307

Open AIRTEspresso opened 2 years ago

AIRTEspresso commented 2 years ago

CFR version

CFR version: 0.152

Compiler

Java openJDK, version: 11.0.13

Description

Here is the 4th case that the code generated by CFR gave different execution results compared with the source code. It is also a little similar with the first issue I submitted, but the difference is that the case occurred only when CFR performed code inlining: in the source code, assignment 'i2 >>>= instanceCount' is executed first, then 'instanceCount -= - 14' and finally the switch expression '(i2 >> 1)% 10 + 87'. However, in the decompiled code, CFR inline the assignment 'i2 >>>= instanceCount' in the switch expression and the assignment 'instanceCount -= - 14' is executed first. The total case is available at error example and I hope it can be helpful.

Example

The source code:

    void mainTest(String[]strArr1){
        long sum = 0;
        for(int l = 1; l < 272; l ++){
            int i1 , i2 = - 130 , i10;
            float f = 1.764F;
            for(i1 = 133; i1 > 2; -- i1){
                instanceCount = 19;
                i10 = 1;
                while(++ i10 < 4){
                    f *= 106;
                    i2 >>>= instanceCount;
                    instanceCount -= - 14;
                    switch((i2 >> 1)% 10 + 87){
                        case 88 : i2 = - 713;
                            i2 +=(int)f;
                            break;
                        case 90 : f *= 23408;
                        case 92 : i2 *= i2;
                            break;
                        case 93 : sum += i1;
                        case 95 : instanceCount += i10;
                    }
                }
            }
        }
        System.out.println("sum = " +  sum);
    }

The code decompiled by CFR:

    void mainTest(String[] stringArray) {
        long l = 0L;
        for (int i = 1; i < 272; ++i) {
            int n = -130;
            float f = 1.764f;
            for (int j = 133; j > 2; --j) {
                this.instanceCount = 19L;
                int n2 = 1;
                while (++n2 < 4) {
                    f *= 106.0f;
                    this.instanceCount -= -14L;
                    switch (((n >>>= (int)this.instanceCount) >> 1) % 10 + 87) {
                        case 88: {
                            n = -713;
                            n += (int)f;
                            break;
                        }
                        case 90: {
                            f *= 23408.0f;
                        }
                        case 92: {
                            n *= n;
                            break;
                        }
                        case 93: {
                            l += (long)j;
                        }
                        case 95: {
                            this.instanceCount += (long)n2;
                        }
                    }
                }
            }
        }
        System.out.println("sum = " + l);
    }