Skip to content

Commit

Permalink
Merge pull request #18130 from theresa-m/nr_verification_4
Browse files Browse the repository at this point in the history
NullRestricted field throws NPE on null assignment in withfield
  • Loading branch information
hangshao0 authored Sep 14, 2023
2 parents 754717a + 3f5b896 commit c53da53
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
10 changes: 10 additions & 0 deletions runtime/vm/BytecodeInterpreter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9697,6 +9697,16 @@ class INTERPRETER_CLASS
goto done;
}

#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES)
if (J9_ARE_ALL_BITS_SET(flags, J9FieldFlagIsNullRestricted)) {
j9object_t valueref = *(j9object_t*)_sp;
if (NULL == valueref) {
rc = THROW_NPE;
goto done;
}
}
#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */

/* need to zero memset the memory so padding bytes are zeroed for memcmp-like comparisons */
copyObjectRef = VM_ValueTypeHelpers::cloneValueType(_currentThread, _objectAccessBarrier, _objectAllocate, objectRefClass, originalObjectRef, true);
if (NULL == copyObjectRef) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public static Class<?> generateNullRestrictedAttributeInArrayField(String classN
return generator.defineClass(className, classBytes, 0, classBytes.length);
}

public static Class<?> generateStaticNullRestrictedFieldAssignedToNull(String className, String fieldClassName) {
public static Class<?> generatePutStaticNullToNullRestrictedField(String className, String fieldClassName) {
String fieldName = "field";

/* Generate field class - value class with ImplicitCreation attribute and ACC_DEFAULT flag set. */
Expand Down Expand Up @@ -126,7 +126,7 @@ public static Class<?> generateStaticNullRestrictedFieldAssignedToNull(String cl
return generator.defineClass(className, classBytes, 0, classBytes.length);
}

public static Class<?> generateInstanceNullRestrictedFieldAssignedToNull(String className, String fieldClassName) {
public static Class<?> generatePutFieldNullToNullRestrictedField(String className, String fieldClassName) {
String fieldName = "field";

/* Generate field class - value class with ImplicitCreation attribute and ACC_DEFAULT flag set. */
Expand Down Expand Up @@ -158,6 +158,41 @@ public static Class<?> generateInstanceNullRestrictedFieldAssignedToNull(String
return generator.defineClass(className, classBytes, 0, classBytes.length);
}

public static Class<?> generateWithFieldStoreNullToNullRestrictedField(String className, String fieldClassName) {
String fieldName = "field";

/* Generate field class - value class with ImplicitCreation attribute and ACC_DEFAULT flag set. */
byte[] fieldClassBytes = generateClass(fieldClassName, ACC_PUBLIC + ACC_FINAL + ValhallaUtils.ACC_VALUE_TYPE,
new Attribute[] {new ImplicitCreationAttribute(ValhallaUtils.ACC_DEFAULT)});
Class<?> fieldClass = generator.defineClass(fieldClassName, fieldClassBytes, 0, fieldClassBytes.length);

ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(ValhallaUtils.CLASS_FILE_MAJOR_VERSION, ACC_PUBLIC + ValhallaUtils.ACC_IDENTITY, className, null, "java/lang/Object", null);

/* instance field of previously generated field class with NullRestrictd attribute */
FieldVisitor fieldVisitor = classWriter.visitField(ACC_PUBLIC, fieldName, fieldClass.descriptorString(), null, null);
fieldVisitor.visitAttribute(new NullRestrictedAttribute());

MethodVisitor mvInit = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mvInit.visitCode();
mvInit.visitVarInsn(ALOAD, 0);
mvInit.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mvInit.visitVarInsn(ALOAD, 0);
mvInit.visitTypeInsn(ValhallaUtils.ACONST_INIT, fieldClass.descriptorString());
mvInit.visitFieldInsn(PUTFIELD, className, fieldName, fieldClass.descriptorString());
mvInit.visitVarInsn(ALOAD, 0);
mvInit.visitFieldInsn(GETFIELD, className, fieldName, fieldClass.descriptorString());
mvInit.visitInsn(ACONST_NULL);
mvInit.visitFieldInsn(ValhallaUtils.WITHFIELD, className, fieldName, fieldClass.descriptorString());
mvInit.visitInsn(RETURN);
mvInit.visitMaxs(2, 1);
mvInit.visitEnd();

classWriter.visitEnd();
byte[] classBytes = classWriter.toByteArray();
return generator.defineClass(className, classBytes, 0, classBytes.length);
}

public static Class<?> findLoadedTestClass(String name) {
return generator.findLoadedClass(name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ static public void testNullRestrictedNotAllowedInArrayTypeField() throws Throwab

/* Instance field with NullRestricted attribute cannot be set to null. */
@Test(expectedExceptions = java.lang.NullPointerException.class)
static public void testNullRestrictedInstanceFieldCannotBeAssignedNull() throws Throwable {
Class<?> c = ValhallaAttributeGenerator.generateInstanceNullRestrictedFieldAssignedToNull("TestNullRestrictedInstanceFieldCannotBeAssignedNull", "TestNullRestrictedInstanceFieldCannotBeAssignedNullField");
static public void testPutFieldNullToNullRestrictedField() throws Throwable {
Class<?> c = ValhallaAttributeGenerator.generatePutFieldNullToNullRestrictedField("TestPutFieldNullToNullRestrictedField", "TestPutFieldNullToNullRestrictedFieldField");
c.newInstance();
}

Expand All @@ -117,9 +117,9 @@ static public void testNullRestrictedInstanceFieldCannotBeAssignedNull() throws
* Since value fields are implicitly final this will always be the case.
*/
@Test
static public void testNullRestrictedStaticFieldCannotBeAssignedNull() throws Throwable {
static public void testPutStaticNullToNullRestrictedField() throws Throwable {
try {
Class<?> c = ValhallaAttributeGenerator.generateStaticNullRestrictedFieldAssignedToNull("testNullRestrictedStaticFieldCannotBeAssignedNull", "testNullRestrictedStaticFieldCannotBeAssignedNullField");
Class<?> c = ValhallaAttributeGenerator.generatePutStaticNullToNullRestrictedField("TestPutStaticNullToNullRestrictedField", "TestPutStaticNullToNullRestrictedFieldField");
c.newInstance();
} catch(java.lang.ExceptionInInitializerError e) {
if (e.getCause() instanceof NullPointerException) {
Expand All @@ -129,4 +129,10 @@ static public void testNullRestrictedStaticFieldCannotBeAssignedNull() throws Th
}
Assert.fail("Test expected a NullPointerException wrapped in ExceptionInInitializerError.");
}

@Test(expectedExceptions = java.lang.NullPointerException.class)
static public void testWithFieldStoreNullToNullRestrictedField() throws Throwable {
Class<?> c = ValhallaAttributeGenerator.generateWithFieldStoreNullToNullRestrictedField("TestWithFieldStoreNullToNullRestrictedField", "TestWithFieldStoreNullToNullRestrictedFieldField");
c.newInstance();
}
}

0 comments on commit c53da53

Please sign in to comment.