Lambda expression fails to capture a reference type local variable in JPF on Java 11
quadhier opened this issue · comments
Problem
This program will cause JPF on Java 11 (java-10-gradle
branch) to crash:
interface I {
void foo();
}
public class Test {
public static void main (String[] args) {
String s = "abc";
I i = () -> {
System.out.println(s);
}
i.foo();
}
}
Bug Diagnosis
The following code snippet sets wrong argument for a reference type free variable of a lambda expression.
jpf-core/src/main/gov/nasa/jpf/vm/FunctionObjectFactory.java
Lines 297 to 301 in 6f6500c
A Tentative Fix
--- a/src/main/gov/nasa/jpf/vm/FunctionObjectFactory.java
+++ b/src/main/gov/nasa/jpf/vm/FunctionObjectFactory.java
@@ -294,11 +294,8 @@ public class FunctionObjectFactory {
if (freeVarValues[i] == null) {
fields.setReferenceValue(i, MJIEnv.NULL);
} else {
- int val = ((ElementInfo) freeVarValues[i]).getObjectRef() + 1;
- // + 1 because when object is created ( i.e GenericHeap.createObject(...)) the value of objRef is initialized
- // to the NamedField value in ElementInfo. But the value needed here is the value of arrayField which
- // NamedField value +1. This is because both array and object fields are created in GenericHeap.newString().
- fields.setReferenceValue(i, val);
+ int objRef = ((ElementInfo) freeVarValues[i]).getObjectRef();
+ fields.setReferenceValue(i, objRef);
}
}
}
The comment in the old version of the code suggests that the +1
is sometimes needed. Can you please check if other cases fail when removing that? Perhaps we need to check the type of object that is created?
The comment in the old version of the code suggests that the +1 is sometimes needed. Can you please check if other cases fail when removing that?
Hi @cyrille-artho, I have confimed that this change won't bring regressions. Here is some additional information:
This snippet of code is imported in this commit and the comment is added in this commit. Both of them are parts of PR #210. And what they are doing is changing implementation of setFuncObjFields()
to fix invokedynamic
for string concat (the long comment also somewhat implies this).
But as the source code of JPF changes, in the current version of JPF, setFuncObjFields()
won't be called in the case of string concat (which is shown below). So I think this change is safe.
jpf-core/src/main/gov/nasa/jpf/vm/FunctionObjectFactory.java
Lines 143 to 147 in 6f6500c
Perhaps we need to check the type of object that is created?
Yes, this is a good idea! We could use freeVarTypeNames
argument of setFuncObjFields()
to check that the type of an object argument is correct.
Okay, I'm working on it.