-
-
Notifications
You must be signed in to change notification settings - Fork 110
Invokedynamic failures #619
Description
Hi there,
I’ve been investigating some failures parsing invokedynamic instructions. I first saw a similar issue raised in #574.
Just noting that I originally encountered the problem in v1.0.0 but it persists in v1.1.0.
I ran into some issues parsing record classes. I was getting various stack underrun errors when attempting to get the bodies of these methods. For example, the record class generates an equals(), hashCode() and string() method by default - all of which trigger an indy.
Public record RecordTest(String a, String b) {
public RecordTest(String a, String b) {
this.a = a;
this.b = b;
}
}
When I attempt to get the method body for equals(), I get the following stack trace:
Exception in thread "main" java.lang.RuntimeException: Failed to convert <jlink.RecordTest: boolean equals(java.lang.Object)>
at sootup.java.bytecode.frontend.AsmMethodSource.resolveBody(AsmMethodSource.java:201)
at sootup.core.model.SootMethod.lazyBodyInitializer(SootMethod.java:95)
at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:166)
at sootup.core.model.SootMethod.getBody(SootMethod.java:134)
at org.ifds.IFDSSetUp.setupSoot(IFDSSetUp.java:68)
at org.ifds.IFDSSetUp.executeStaticAnalysis(IFDSSetUp.java:30)
at org.ifds.Main.main(Main.java:15)
Caused by: java.lang.RuntimeException: Stack underrun
at sootup.java.bytecode.frontend.OperandStack.pop(OperandStack.java:90)
at sootup.java.bytecode.frontend.OperandStack.popImmediate(OperandStack.java:162)
at sootup.java.bytecode.frontend.OperandStack.popImmediate(OperandStack.java:172)
at sootup.java.bytecode.frontend.AsmMethodSource.convertInvokeDynamicInsn(AsmMethodSource.java:1341)
at sootup.java.bytecode.frontend.AsmMethodSource.convert(AsmMethodSource.java:1759)
at sootup.java.bytecode.frontend.AsmMethodSource.resolveBody(AsmMethodSource.java:198)
... 6 more
I think the issue lies here https://github.com/soot-oss/SootUp/blob/v1.1.0/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1171
My understanding is we shouldn’t pop the operand stack to generate the method handle, as this leaves us with an empty stack when we generate the arguments here https://github.com/soot-oss/SootUp/blob/v1.1.0/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1354.
I’ve currently been working around this by adding a dummy “unknown value”, as opposed to popping the operand stack.
Aside from that, I think there some logic issues in this stretch of code:
The variable nrArgs is set to the size - 1 to account for arrays starting at 0, however in line 1391 (https://github.com/soot-oss/SootUp/blob/v1.1.0/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#LL1391C1-L1392C1), we preemptively decrease the value of nrArgs by 1 again before entering the while statement, meaning we are never popping the full extent of the operand stack.
Finally, I think the check if the expression is a static invocation here is backwards (https://github.com/soot-oss/SootUp/blob/v1.1.0/sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1394).
If the expression is static, we’d like to pop the stack once more, not the other way around.
Apologies for the convoluted message in advance! Resolving the 2 issues I mentioned above helped me get rid of the error messages I was getting but I’d much rather verify if this is correct.
Thanks!
Sonia