From e5aef5ee9d10736344be2fd4fa6b07af074eb949 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 30 Oct 2013 10:48:32 -0700 Subject: [PATCH] Protect against NPE when resolving generic array Update ResolvableType to check that the resolved component type from a generic array is not null before attempting to use it to generate the resolved array class. Issue: SPR-11044 --- .../springframework/core/ResolvableType.java | 3 +- .../core/GenericTypeResolverTests.java | 28 +++++++++++++++++++ .../core/ResolvableTypeTests.java | 26 +++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 80e9174d4c..7ec5f032d9 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -575,7 +575,8 @@ public final class ResolvableType implements Serializable { return (Class) this.type; } if (this.type instanceof GenericArrayType) { - return Array.newInstance(getComponentType().resolve(), 0).getClass(); + Class resolvedComponent = getComponentType().resolve(); + return (resolvedComponent == null ? null : Array.newInstance(resolvedComponent, 0).getClass()); } return resolveType().resolve(); } diff --git a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java index f0d728eb82..b6b42006fb 100644 --- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java @@ -144,6 +144,24 @@ public class GenericTypeResolverTests { assertThat(resolved, equalTo(new Class[] { Object.class })); } + @Test + public void getGenericsOnArrayFromParamCannotBeResolved() throws Exception { + // SPR-11044 + MethodParameter methodParameter = MethodParameter.forMethodOrConstructor( + WithArrayBase.class.getDeclaredMethod("array", Object[].class), 0); + Class resolved = GenericTypeResolver.resolveParameterType(methodParameter, WithArray.class); + assertThat(resolved, equalTo((Class) Object[].class)); + } + + @Test + public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception { + // SPR-11044 + Class resolved = GenericTypeResolver.resolveReturnType( + WithArrayBase.class.getDeclaredMethod("array", Object[].class), + WithArray.class); + assertThat(resolved, equalTo((Class) Object[].class)); + } + public interface MyInterfaceType { } @@ -279,4 +297,14 @@ public class GenericTypeResolverTests { } } + static abstract class WithArrayBase { + + public abstract T[] array(T... args); + + } + + static abstract class WithArray extends WithArrayBase { + + } + } diff --git a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java index 24db8da68d..04e727d804 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -519,6 +519,30 @@ public class ResolvableTypeTests { assertThat(generic.resolve(), equalTo((Class) String[].class)); } + @Test + public void resolveVariableGenericArray() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"), TypedFields.class); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(), equalTo((Class) String[].class)); + } + + @Test + public void resolveVariableGenericArrayUnknown() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray")); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(), nullValue()); + } + + @Test + public void resolveVariableGenericArrayUnknownWithFallback() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray")); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(Object.class), equalTo((Class) Object.class)); + } + @Test public void resolveWildcardTypeUpperBounds() throws Exception { ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType")); @@ -1253,6 +1277,8 @@ public class ResolvableTypeTests { public Map, Map> nested; + public T[] variableTypeGenericArray; + }