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

Type argument of null reference generic class variables is converted to Object #340

Open
xxh160 opened this issue May 2, 2023 · 0 comments
Labels

Comments

@xxh160
Copy link

xxh160 commented May 2, 2023

Hi! I am doing some research based on CFR! I have found a potential issue in the decompilation process of CFR: It seems that when a null reference generic class variable is decompiled, its type argument is being converted to Object.

Here is an example:

class T1<K> {
}

class T2<Q> extends T1<Integer> {
}

class Demo1 {
    public T1<Integer> foo(Boolean b1) {
        final T1<Integer> t1 = (T1<Integer>) null;
        return ((b1) ? t1 : new T2<Double>());
    }
}

After being decompiled with CFR, the output is:

/*
 * Decompiled with CFR 0.153-SNAPSHOT (24c7433-dirty).
 */
class Demo1 {
    Demo1() {
    }

    public T1<Integer> foo(Boolean bl) {
        T1<Object> t1 = null;
        return bl != false ? t1 : new T2();
    }
}

The variable t1 loses its type argument Integer, and its type is transformed into T1<Object> undesirably.

In addition, during extended research on this sample, it was discovered that if the reference value is not null, it may trigger semantic errors:

class T1<K extends Integer, U extends Double> {
    public String print() {
        return "T1";
    }
}

class T2<P, Q> extends T1<Integer, Double> {
    public String print() {
        return "T2";
    }
}

class Demo2 {
    public T1<Integer, Double> foo(Boolean b1) {
        final T1<Integer, Double> t1 = new T1<>();
        return ((b1) ? t1 : new T2<Integer, Double>());
    }

    public static void main(String[] args) {
        Demo2 d = new Demo2();
        Boolean b1 = true;
        T1<Integer, Double> t1 = d.foo(b1);
        // Should be true
        System.out.println("T1".equals(t1.print()));
    }
}

After being decompiled with CFR, the output is:

/*
 * Decompiled with CFR 0.153-SNAPSHOT (24c7433-dirty).
 */
class Demo2 {
    Demo2() {
    }

    public T1<Integer, Double> foo(Boolean bl) {
        T2 t2 = new T2();
        return bl != false ? t2 : new T2();
    }

    public static void main(String[] stringArray) {
        Demo2 demo2 = new Demo2();
        Boolean bl = true;
        T1<Integer, Double> t1 = demo2.foo(bl);
        System.out.println("T1".equals(t1.print()));
    }
}

The results are different between running the source code directly and running the decompiled code: the result of running the source code is true, while the result of running the decompiled code is false.

Would you please have a look at this? It is important for me!
Thanks a lot!

CFR version: CFR 0.153-SNAPSHOT (24c7433-dirty).
Javac version: openjdk 11.0.18 2023-01-17.
I also attach the source files and I hope they will be helpful: demo.zip.

@xxh160 xxh160 added the bug label May 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant