DATACMNS-1200 - Guard casts to primitive type in ClassGeneratingEntityInstantiator.

We now insert assertions for primitive types before passing these to the actual constructor to prevent NullPointerExceptions. We also output the index/parameter name if the parameter was null.

Original pull request: #255.
This commit is contained in:
Mark Paluch
2017-10-18 14:27:05 +02:00
committed by Oliver Gierke
parent 32536067f1
commit 78bd8fb0f7
2 changed files with 32 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.asm.ClassWriter;
@@ -399,6 +400,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
Constructor<?> ctor = constructor.getConstructor();
Class<?>[] parameterTypes = ctor.getParameterTypes();
List<? extends Parameter<Object, ?>> parameters = constructor.getParameters();
for (int i = 0; i < parameterTypes.length; i++) {
@@ -409,6 +411,11 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
mv.visitInsn(AALOAD);
if (parameterTypes[i].isPrimitive()) {
mv.visitInsn(DUP);
String parameterName = parameters.size() > i ? parameters.get(i).getName() : null;
insertAssertNotNull(mv, parameterName == null ? String.format("at index %d", i) : parameterName);
insertUnboxInsns(mv, Type.getType(parameterTypes[i]).toString().charAt(0), "");
} else {
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(parameterTypes[i]));
@@ -438,6 +445,20 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
mv.visitLdcInsn(idx);
}
/**
* Insert not {@literal null} assertion for a parameter.
*
* @param mv the method visitor into which instructions should be inserted
* @param parameterName name of the parameter to create the appropriate assertion message.
*/
private void insertAssertNotNull(MethodVisitor mv, String parameterName) {
// Assert.notNull(property)
mv.visitLdcInsn(String.format("Parameter %s must not be null!", parameterName));
mv.visitMethodInsn(INVOKESTATIC, "org/springframework/util/Assert", "notNull",
String.format("(%s%s)V", String.format("L%s;", JAVA_LANG_OBJECT), "Ljava/lang/String;"), false);
}
/**
* Insert any necessary cast and value call to convert from a boxed type to a primitive value.
* <p>