Skip to content

Commit ea2843e

Browse files
committed
MethodInvokeTypeProvider lazily invokes target method (avoiding deserialization exploits)
Issue: SPR-13656
1 parent a1bf941 commit ea2843e

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* {@link GenericArrayType#getGenericComponentType()}) will be automatically wrapped.
5252
*
5353
* @author Phillip Webb
54+
* @author Juergen Hoeller
5455
* @since 4.0
5556
*/
5657
abstract class SerializableTypeWrapper {
@@ -210,7 +211,7 @@ public Object getSource() {
210211

211212

212213
/**
213-
* {@link Serializable} {@link InvocationHandler} used by the Proxied {@link Type}.
214+
* {@link Serializable} {@link InvocationHandler} used by the proxied {@link Type}.
214215
* Provides serialization support and enhances any methods that return {@code Type}
215216
* or {@code Type[]}.
216217
*/
@@ -373,21 +374,27 @@ static class MethodInvokeTypeProvider implements TypeProvider {
373374

374375
private final int index;
375376

376-
private transient Object result;
377+
private transient Method method;
378+
379+
private transient volatile Object result;
377380

378381
public MethodInvokeTypeProvider(TypeProvider provider, Method method, int index) {
379382
this.provider = provider;
380383
this.methodName = method.getName();
381384
this.index = index;
382-
this.result = ReflectionUtils.invokeMethod(method, provider.getType());
385+
this.method = method;
383386
}
384387

385388
@Override
386389
public Type getType() {
387-
if (this.result instanceof Type || this.result == null) {
388-
return (Type) this.result;
390+
Object result = this.result;
391+
if (result == null) {
392+
// Lazy invocation of the target method
393+
result = ReflectionUtils.invokeMethod(this.method, this.provider.getType());
394+
// Cache the result for further calls
395+
this.result = result;
389396
}
390-
return ((Type[])this.result)[this.index];
397+
return (result instanceof Type[] ? ((Type[]) result)[this.index] : (Type) result);
391398
}
392399

393400
@Override
@@ -397,8 +404,8 @@ public Object getSource() {
397404

398405
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
399406
inputStream.defaultReadObject();
400-
Method method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
401-
this.result = ReflectionUtils.invokeMethod(method, this.provider.getType());
407+
this.method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
408+
Assert.state(this.method.getReturnType() == Type.class || this.method.getReturnType() == Type[].class);
402409
}
403410
}
404411

0 commit comments

Comments
 (0)