Broken synchronized block in unpacker_u.a([BI[BII)I #94

Closed
opened 4 years ago by gpe · 4 comments
gpe commented 4 years ago
Owner
public static int method4961(@OriginalArg(0) byte[] var0, @OriginalArg(1) int var1, @OriginalArg(2) byte[] var2, @OriginalArg(3) int var3) {
	@Pc(1) Class204 var5 = aClass204_1;
	synchronized(var5){}

	@Pc(45) int var4;
	try {
		aClass204_1.aByteArray78 = var2;
		aClass204_1.anInt6118 = 9;
		aClass204_1.aByteArray79 = var0;
		aClass204_1.anInt6120 = 0;
		aClass204_1.anInt6121 = var1;
		aClass204_1.anInt6125 = 0;
		aClass204_1.anInt6124 = 0;
		aClass204_1.anInt6119 = 0;
		aClass204_1.anInt6122 = 0;
		method4963(aClass204_1);
		@Pc(37) int var9 = var1 - aClass204_1.anInt6121;
		aClass204_1.aByteArray78 = null;
		aClass204_1.aByteArray79 = null;
		var4 = var9;
		@Pc(46) Object var10000 = null;
	} catch (@Pc(50) Throwable var8) {
		throw var8;
	}

	return var4;
}
``` public static int method4961(@OriginalArg(0) byte[] var0, @OriginalArg(1) int var1, @OriginalArg(2) byte[] var2, @OriginalArg(3) int var3) { @Pc(1) Class204 var5 = aClass204_1; synchronized(var5){} @Pc(45) int var4; try { aClass204_1.aByteArray78 = var2; aClass204_1.anInt6118 = 9; aClass204_1.aByteArray79 = var0; aClass204_1.anInt6120 = 0; aClass204_1.anInt6121 = var1; aClass204_1.anInt6125 = 0; aClass204_1.anInt6124 = 0; aClass204_1.anInt6119 = 0; aClass204_1.anInt6122 = 0; method4963(aClass204_1); @Pc(37) int var9 = var1 - aClass204_1.anInt6121; aClass204_1.aByteArray78 = null; aClass204_1.aByteArray79 = null; var4 = var9; @Pc(46) Object var10000 = null; } catch (@Pc(50) Throwable var8) { throw var8; } return var4; } ```
gpe added the
bug
deobfuscator
labels 4 years ago
Poster
Owner

There might be more of these in the non-GL client.

There might be more of these in the non-GL client.
Poster
Owner

I think it might be related to ASM's JSR inliner.

I think it might be related to ASM's JSR inliner.
Poster
Owner

The underlying cause is that the exact way synchronized (...) blocks are compiled has changed over the years. Fernflower doesn't recognize the bytecode that javac 1.1 and 1.2 output.

Here's a program demonstrating the differences:

class Test {
	static Object lock = new Object();

	static int test() {
		synchronized (lock) {
			return 123456;
		}
	}
}

javac 1.1:

class Test {
  static java.lang.Object lock;

  static int test();
    Code:
       0: getstatic     #5                  // Field lock:Ljava/lang/Object;
       3: astore_1
       4: aload_1
       5: monitorenter
       6: ldc           #1                  // int 123456
       8: istore_0
       9: jsr           17
      12: iload_0
      13: ireturn
      14: aload_1
      15: monitorexit
      16: athrow
      17: astore_2
      18: aload_1
      19: monitorexit
      20: ret           2
    Exception table:
       from    to  target type
           6    14    14   any

  Test();
    Code:
       0: aload_0
       1: invokespecial #4                  // Method java/lang/Object."<init>":()V
       4: return

  static {};
    Code:
       0: new           #3                  // class java/lang/Object
       3: dup
       4: invokespecial #4                  // Method java/lang/Object."<init>":()V
       7: putstatic     #5                  // Field lock:Ljava/lang/Object;
      10: return
}

javac 1.2:

class Test {
  static java.lang.Object lock;

  static {};
    Code:
       0: new           #3                  // class java/lang/Object
       3: dup
       4: invokespecial #4                  // Method java/lang/Object."<init>":()V
       7: putstatic     #5                  // Field lock:Ljava/lang/Object;
      10: return

  Test();
    Code:
       0: aload_0
       1: invokespecial #4                  // Method java/lang/Object."<init>":()V
       4: return

  static int test();
    Code:
       0: getstatic     #5                  // Field lock:Ljava/lang/Object;
       3: astore_1
       4: aload_1
       5: monitorenter
       6: ldc           #1                  // int 123456
       8: istore_0
       9: jsr           17
      12: iload_0
      13: ireturn
      14: aload_1
      15: monitorexit
      16: athrow
      17: astore_2
      18: aload_1
      19: monitorexit
      20: ret           2
    Exception table:
       from    to  target type
           6    14    14   any
}

javac 1.3:

class Test {
  static java.lang.Object lock;

  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  static int test();
    Code:
       0: getstatic     #2                  // Field lock:Ljava/lang/Object;
       3: astore_0
       4: aload_0
       5: monitorenter
       6: ldc           #3                  // int 123456
       8: istore_1
       9: aload_0
      10: monitorexit
      11: iload_1
      12: ireturn
      13: astore_2
      14: aload_0
      15: monitorexit
      16: aload_2
      17: athrow
    Exception table:
       from    to  target type
           6    13    13   any

  static {};
    Code:
       0: new           #4                  // class java/lang/Object
       3: dup
       4: invokespecial #1                  // Method java/lang/Object."<init>":()V
       7: putstatic     #2                  // Field lock:Ljava/lang/Object;
      10: return
}

javac 1.4:

class Test {
  static java.lang.Object lock;

  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  static int test();
    Code:
       0: getstatic     #2                  // Field lock:Ljava/lang/Object;
       3: dup
       4: astore_0
       5: monitorenter
       6: ldc           #3                  // int 123456
       8: aload_0
       9: monitorexit
      10: ireturn
      11: astore_1
      12: aload_0
      13: monitorexit
      14: aload_1
      15: athrow
    Exception table:
       from    to  target type
           6    10    11   any
          11    14    11   any

  static {};
    Code:
       0: new           #4                  // class java/lang/Object
       3: dup
       4: invokespecial #1                  // Method java/lang/Object."<init>":()V
       7: putstatic     #2                  // Field lock:Ljava/lang/Object;
      10: return
}
The underlying cause is that the exact way `synchronized (...)` blocks are compiled has changed over the years. Fernflower doesn't recognize the bytecode that javac 1.1 and 1.2 output. Here's a program demonstrating the differences: ```java class Test { static Object lock = new Object(); static int test() { synchronized (lock) { return 123456; } } } ``` javac 1.1: ``` class Test { static java.lang.Object lock; static int test(); Code: 0: getstatic #5 // Field lock:Ljava/lang/Object; 3: astore_1 4: aload_1 5: monitorenter 6: ldc #1 // int 123456 8: istore_0 9: jsr 17 12: iload_0 13: ireturn 14: aload_1 15: monitorexit 16: athrow 17: astore_2 18: aload_1 19: monitorexit 20: ret 2 Exception table: from to target type 6 14 14 any Test(); Code: 0: aload_0 1: invokespecial #4 // Method java/lang/Object."<init>":()V 4: return static {}; Code: 0: new #3 // class java/lang/Object 3: dup 4: invokespecial #4 // Method java/lang/Object."<init>":()V 7: putstatic #5 // Field lock:Ljava/lang/Object; 10: return } ``` javac 1.2: ``` class Test { static java.lang.Object lock; static {}; Code: 0: new #3 // class java/lang/Object 3: dup 4: invokespecial #4 // Method java/lang/Object."<init>":()V 7: putstatic #5 // Field lock:Ljava/lang/Object; 10: return Test(); Code: 0: aload_0 1: invokespecial #4 // Method java/lang/Object."<init>":()V 4: return static int test(); Code: 0: getstatic #5 // Field lock:Ljava/lang/Object; 3: astore_1 4: aload_1 5: monitorenter 6: ldc #1 // int 123456 8: istore_0 9: jsr 17 12: iload_0 13: ireturn 14: aload_1 15: monitorexit 16: athrow 17: astore_2 18: aload_1 19: monitorexit 20: ret 2 Exception table: from to target type 6 14 14 any } ``` javac 1.3: ``` class Test { static java.lang.Object lock; Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return static int test(); Code: 0: getstatic #2 // Field lock:Ljava/lang/Object; 3: astore_0 4: aload_0 5: monitorenter 6: ldc #3 // int 123456 8: istore_1 9: aload_0 10: monitorexit 11: iload_1 12: ireturn 13: astore_2 14: aload_0 15: monitorexit 16: aload_2 17: athrow Exception table: from to target type 6 13 13 any static {}; Code: 0: new #4 // class java/lang/Object 3: dup 4: invokespecial #1 // Method java/lang/Object."<init>":()V 7: putstatic #2 // Field lock:Ljava/lang/Object; 10: return } ``` javac 1.4: ``` class Test { static java.lang.Object lock; Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return static int test(); Code: 0: getstatic #2 // Field lock:Ljava/lang/Object; 3: dup 4: astore_0 5: monitorenter 6: ldc #3 // int 123456 8: aload_0 9: monitorexit 10: ireturn 11: astore_1 12: aload_0 13: monitorexit 14: aload_1 15: athrow Exception table: from to target type 6 10 11 any 11 14 11 any static {}; Code: 0: new #4 // class java/lang/Object 3: dup 4: invokespecial #1 // Method java/lang/Object."<init>":()V 7: putstatic #2 // Field lock:Ljava/lang/Object; 10: return } ```
Poster
Owner

Fixed in 2862b305c5

Fixed in 2862b305c50061d3d98a63b2caca05d6e36d262a
gpe closed this issue 4 years ago
Sign in to join this conversation.
Loading…
There is no content yet.