Skip to content

Commit e5aef5e

Browse files
author
Phillip Webb
committed
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
1 parent a7af950 commit e5aef5e

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

spring-core/src/main/java/org/springframework/core/ResolvableType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ private Class<?> resolveClass() {
575575
return (Class<?>) this.type;
576576
}
577577
if (this.type instanceof GenericArrayType) {
578-
return Array.newInstance(getComponentType().resolve(), 0).getClass();
578+
Class<?> resolvedComponent = getComponentType().resolve();
579+
return (resolvedComponent == null ? null : Array.newInstance(resolvedComponent, 0).getClass());
579580
}
580581
return resolveType().resolve();
581582
}

spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,24 @@ public void getGenericsCannotBeResovled() throws Exception {
144144
assertThat(resolved, equalTo(new Class[] { Object.class }));
145145
}
146146

147+
@Test
148+
public void getGenericsOnArrayFromParamCannotBeResolved() throws Exception {
149+
// SPR-11044
150+
MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(
151+
WithArrayBase.class.getDeclaredMethod("array", Object[].class), 0);
152+
Class<?> resolved = GenericTypeResolver.resolveParameterType(methodParameter, WithArray.class);
153+
assertThat(resolved, equalTo((Class) Object[].class));
154+
}
155+
156+
@Test
157+
public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception {
158+
// SPR-11044
159+
Class<?> resolved = GenericTypeResolver.resolveReturnType(
160+
WithArrayBase.class.getDeclaredMethod("array", Object[].class),
161+
WithArray.class);
162+
assertThat(resolved, equalTo((Class) Object[].class));
163+
}
164+
147165
public interface MyInterfaceType<T> {
148166
}
149167

@@ -279,4 +297,14 @@ class TypedNested extends Nested<Long> {
279297
}
280298
}
281299

300+
static abstract class WithArrayBase<T> {
301+
302+
public abstract T[] array(T... args);
303+
304+
}
305+
306+
static abstract class WithArray<T> extends WithArrayBase<T> {
307+
308+
}
309+
282310
}

spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,30 @@ public void resolveGenericArrayFromGeneric() throws Exception {
519519
assertThat(generic.resolve(), equalTo((Class) String[].class));
520520
}
521521

522+
@Test
523+
public void resolveVariableGenericArray() throws Exception {
524+
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"), TypedFields.class);
525+
assertThat(type.getType().toString(), equalTo("T[]"));
526+
assertThat(type.isArray(), equalTo(true));
527+
assertThat(type.resolve(), equalTo((Class) String[].class));
528+
}
529+
530+
@Test
531+
public void resolveVariableGenericArrayUnknown() throws Exception {
532+
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
533+
assertThat(type.getType().toString(), equalTo("T[]"));
534+
assertThat(type.isArray(), equalTo(true));
535+
assertThat(type.resolve(), nullValue());
536+
}
537+
538+
@Test
539+
public void resolveVariableGenericArrayUnknownWithFallback() throws Exception {
540+
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
541+
assertThat(type.getType().toString(), equalTo("T[]"));
542+
assertThat(type.isArray(), equalTo(true));
543+
assertThat(type.resolve(Object.class), equalTo((Class) Object.class));
544+
}
545+
522546
@Test
523547
public void resolveWildcardTypeUpperBounds() throws Exception {
524548
ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType"));
@@ -1253,6 +1277,8 @@ static class Fields<T> {
12531277

12541278
public Map<Map<String, Integer>, Map<Byte, Long>> nested;
12551279

1280+
public T[] variableTypeGenericArray;
1281+
12561282
}
12571283

12581284

0 commit comments

Comments
 (0)