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

Method of lambda expression passed as an instance of an interface defined in obfuscated library is not obfuscated correclty #405

Open
patrick96 opened this issue May 22, 2024 · 0 comments

Comments

@patrick96
Copy link

When building against an obfuscated library (providing its mapping file using -applymapping), I have noticed that lambda expressions which represent an implementation of an interface do not get obfuscated correctly when that interface is part of the obfuscated library.
At runtime this produces an AbstractMethodError because the interface's single member method was renamed, but the lambda instance still has the unobfuscated method name.

Steps to Reproduce

The idea is to build an obfuscated library defining an interface and an application defining a lambda

lib_stripped.jar

Interface.java

interface Interface {
  void doSomething(int x);
}

Lib.java

public class Lib {
  public static void call(Interface i, int x) {
    System.out.println("methods:");
    for (var m : i.getClass().getDeclaredMethods()) {
      System.out.println("\t" + m);
    }
    i.doSomething(x);
  }
}

lib.pro

-injars lib.jar
-outjars lib_stripped.jar

-libraryjars  <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)

-printmapping lib_stripped.map

-useuniqueclassmembernames
-dontoptimize
-dontshrink

To build lib_stripped.jar:

javac Lib.java Interface.java
jar cf lib.jar Lib.class Interface.class
proguard-7.4.2/bin/proguard.sh -include lib.pro

app_stripped.jar

Main.java

public class Main {
  public static void main(String[] args) {
    Lib.call((x) -> { System.out.println(x + 1); }, 100);
  }
}

app.pro

-injars app.jar
-outjars app_stripped.jar

-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
-libraryjars lib.jar(!META-INF/versions/**,!module-info.class)

-applymapping lib_stripped.map
-printmapping app_stripped.map

-useuniqueclassmembernames
-dontoptimize
-dontshrink

-keep public class Main {
    public static void main(java.lang.String[]);
}

To build app_stripped.jar:

javac -cp lib.jar Main.java
jar -c -f app.jar -e Main.class Main.class
proguard-7.4.2/bin/proguard.sh -include app.pro

Now when we run this, we get an AbstractMethodError and see that the method defined on the passed object is still called doSomething:

$ java -cp lib_stripped.jar:app_stripped.jar Main
methods:
        public void Main$$Lambda/0x000071a1e8001800.doSomething(int)
Exception in thread "main" java.lang.AbstractMethodError: Receiver class Main$$Lambda/0x000071a1e8001800 does not define or inherit an implementation of the resolved method 'abstract void a(int)' of interface a.
        at b.a(Unknown Source)
        at Main.main(Unknown Source)

Additional context

If you run with the unobfuscated jars, you get the expected output:

$ java -cp lib.jar:app.jar Main
methods:
        public void Main$$Lambda/0x00007baadc001800.doSomething(int)
101
@patrick96 patrick96 changed the title AbstractMethodError at runtime when lambda expression is passed as an instance of an interface defined in obfuscated library Method of lambda expression passed as an instance of an interface defined in obfuscated library is not obfuscated correclty May 22, 2024
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