procyon icon indicating copy to clipboard operation
procyon copied to clipboard

IndexOutOfBoundsExceptions

Open jdelker opened this issue 2 years ago • 2 comments

When decompiling particular classes, I sometimes encounter IndexOutOfBoundsExceptions, which manifest in the decompiled code as shown below:

//           
// This method could not be decompiled.          
//           
// Original Bytecode:          
//           
//  [...]      
//           
// The error that occurred was:          
//           
// java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0          
//     at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)          
//     at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)          
//     at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
//     [...]

I tried to look into this myself, but I had to realize, that I just understand too little of the decompilation process to find the root cause. This problem is present since I started using your marvelous decompiler back in 2018 and also applies to the most recent v0.6.0 release. Due to the fact, that I used the decompiler primarily on licensed legacy code, I never found a way to provide some reproduction steps here.

Well, up to now. By accident I found another class, that shows the same problem, but is freely available - compiled and in source. (BTW: There is surely no need to decompile kotlin-stdlib, but as it shows the exact same exception as on the legacy java code, I use it for reproduction here.)

So, please consider the following reproduction steps:

  1. Download Kotlin-Stdlib (https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.20/kotlin-stdlib-1.7.20.jar)
  2. Perform decompile on this JAR (my command was java -jar procyon-decompiler-0.6.0.jar -ln -sl -o /tmp/out kotlin-stdlib-1.7.20.jar
  3. Open /tmp/out/kotlin/SynchronizedLazyImpl.java and find the inline comments of the decompiler logging the java.lang.IndexOutOfBoundsException.

Some observations:

  • There seem to be several inline exceptions in other classes, too, but with other causes. I don't want to overcomplicate things in this issue, so I'm fine with sticking to the IndexOutOfBoundsException for now.
  • While most of the exceptions happen silently (only within the inline-comments of decompiled classes), one IndexOutOfBoundsException is actually thrown in the console (after Decompiling kotlin/text/StringsKt__StringsKt...). But this one seems unrelated to the one in SynchronizedLazyImpl.java.

If you require more details (like the full inline comment), let me know. I didn't want to blow up the description here.

jdelker avatar Oct 31 '22 15:10 jdelker

Inline comment found in SynchronizedLazyImpl.java:

//           
// This method could not be decompiled.          
//           
// Original Bytecode:          
//           
//     1: getfield        kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;          
//     4: astore_1        /* _v1 */          
//     5: aload_1         /* _v1 */          
//     6: getstatic       kotlin/UNINITIALIZED_VALUE.INSTANCE:Lkotlin/UNINITIALIZED_VALUE;          
//     9: if_acmpeq       14          
//    12: aload_1         /* _v1 */          
//    13: areturn                  
//    14: aload_0         /* this */          
//    15: getfield        kotlin/SynchronizedLazyImpl.lock:Ljava/lang/Object;          
//    18: astore_2                 
//    19: aload_2                  
//    20: astore_3                 
//    21: aload_3                  
//    22: monitorenter             
//    23: nop                      
//    24: iconst_0                 
//    25: istore          $i$a$-synchronized-SynchronizedLazyImpl$value$1          
//    27: aload_0         /* this */          
//    28: getfield        kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;          
//    31: astore          _v2          
//    33: aload           _v2          
//    35: getstatic       kotlin/UNINITIALIZED_VALUE.INSTANCE:Lkotlin/UNINITIALIZED_VALUE;          
//    38: if_acmpeq       46          
//    41: aload           _v2          
//    43: goto            74          
//    46: aload_0         /* this */          
//    47: getfield        kotlin/SynchronizedLazyImpl.initializer:Lkotlin/jvm/functions/Function0;          
//    50: dup                      
//    51: invokestatic    kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V          
//    54: invokeinterface kotlin/jvm/functions/Function0.invoke:()Ljava/lang/Object;          
//    59: astore          typedValue          
//    61: aload_0         /* this */          
//    62: aload           typedValue          
//    64: putfield        kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;          
//    67: aload_0         /* this */          
//    68: aconst_null              
//    69: putfield        kotlin/SynchronizedLazyImpl.initializer:Lkotlin/jvm/functions/Function0;          
//    72: aload           typedValue          
//    74: nop                      
//    75: astore          null          
//    77: aload_3                  
//    78: monitorexit              
//    79: aload           4          
//    81: goto            91          
//    84: astore          4          
//    86: aload_3                  
//    87: monitorexit              
//    88: aload           4          
//    90: athrow                   
//    91: areturn                  
//    Signature:          
//  ()TT;          
//    StackMapTable: 00 05 FC 00 0E 07 00 05 FF 00 1F 00 06 07 00 02 07 00 05 07 00 05 07 00 05 01 07 00 05 00 00 5B 07 00 05 FF 00 09 00 04 07 00 02 07 00 05 07 00 05 07 00 05 00 01 07 00 41 FF 00 06 00 06 07 00 02 07 00 05 07 00 05 07 00 05 07 00 05 07 00 05 00 01 07 00 05          
//    Exceptions:          
//  Try           Handler          
//  Start  End    Start  End    Type          
//  -----  -----  -----  -----  ----          
//  23     77     84     91     Any          
//  84     86     84     91     Any          
//           
// The error that occurred was:          
//           
// java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0          
//     at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)          
//     at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)          
//     at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)          
//     at java.base/java.util.Objects.checkIndex(Objects.java:372)          
//     at java.base/java.util.ArrayList.remove(ArrayList.java:536)          
//     at com.strobel.assembler.ir.StackMappingVisitor.pop(StackMappingVisitor.java:267)          
//     at com.strobel.assembler.ir.StackMappingVisitor$InstructionAnalyzer.execute(StackMappingVisitor.java:599)          
//     at com.strobel.assembler.ir.StackMappingVisitor$InstructionAnalyzer.visit(StackMappingVisitor.java:398)
//     at com.strobel.decompiler.ast.AstBuilder.performStackAnalysis(AstBuilder.java:2086)
//     at com.strobel.decompiler.ast.AstBuilder.build(AstBuilder.java:108)
//     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:203)
//     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
//     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
//     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
//     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
//     at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
//     at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
//     at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:144)
// 

jdelker avatar Nov 02 '22 08:11 jdelker