Guardsquare / proguard

ProGuard, Java optimizer and obfuscator
https://www.guardsquare.com/en/products/proguard
GNU General Public License v2.0
2.89k stars 414 forks source link

java.lang.VerifyError: Bad return type #434

Closed OwenLiuBo closed 2 months ago

OwenLiuBo commented 2 months ago

I tried to use Proguard 7.5 to obfuscate the following code:

package test;

import java.sql.Timestamp;
import java.util.*;

public class test {
  public static void main(String[] args) throws Exception {
    System.out.println(test(null));
  }

  private static Date test(Object timezone) {
    Date date;

    Calendar calendar = Calendar.getInstance();
    if (timezone == null) {
      date = new Timestamp(124, 8, 11, 3, 17, 8, 123456789);
    } else {
      calendar.setTimeZone((TimeZone)timezone);
      date = calendar.getTime();
    }

    return date;
  }
}

but the obfuscated code throws following exception:

Error: Unable to initialize main class test.test
Caused by: java.lang.VerifyError: Bad return type
Exception Details:
  Location:
    test/test.test(Ljava/lang/Object;)Ljava/util/Date; @46: areturn
  Reason:
    Type 'java/lang/Object' (current frame, stack[0]) is not assignable to 'java/util/Date' (from method signature)
  Current Frame:
    bci: @46
    flags: { }
    locals: { top, 'java/lang/Object' }
    stack: { 'java/lang/Object' }
  Bytecode:
    0000000: b800 0e4d 2ac7 001b bb00 0659 107c 1008
    0000010: 100b 0610 1110 0812 01b7 000d 4ca7 0010
    0000020: 2c2a c000 08b6 0010 2cb6 000f 4c2b b0
  Stackmap Table:
    append_frame(@32,Top,Object[#7])
    full_frame(@45,{Top,Object[#4]},{})

The obfuscation configuration is:

-injars bin/test.jar
-outjars obfus/test.jar

-dontoptimize
-dontusemixedcaseclassnames
-dontobfuscate

-keep class * {
    public *** *(...);
}
mrjameshamilton commented 2 months ago

According to your configuration, you have no -libraryjars which ProGuard needs to perform preverification correctly. There are probably warnings printed about missing classes.

If you're using Java >8: in your case, you'll need to add at least the base jmod and the sql jmod:

-libraryjars /path/to/jdk/jmods/java.base.jmod
-libraryjars /path/to/jdk/jmods/java.sql.jmod

If using Java <=8: then you'll need to add the rt.jar e.g.

-libraryjars /path/to/jdk/lib/rt.jar
OwenLiuBo commented 2 months ago

It works! Thanks, James. You saved my day. :-)

Just put more information about this perhaps will save someone's time as well. I used -dontwarn option for ProGuard. This is the reason why I didn't see the warnings. If no this, the output will be:

Initializing...
Warning: test.test: can't find referenced class java.sql.Timestamp
Warning: test.test: can't find referenced class java.sql.Timestamp
Warning: there were 2 unresolved references to classes or interfaces.
         You may need to add missing library jars or update their versions.
         If your code works fine without the missing classes, you can suppress
         the warnings with '-dontwarn' options.
         (https://www.guardsquare.com/proguard/manual/troubleshooting#unresolvedclass)
Unexpected error