Browse Source

MethodInvokeTypeProvider lazily invokes target method (avoiding deserialization exploits)

Issue: SPR-13656
pull/916/head
Juergen Hoeller 9 years ago
parent
commit
ea2843ecc0
  1. 23
      spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java

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

@ -51,6 +51,7 @@ import org.springframework.util.ReflectionUtils; @@ -51,6 +51,7 @@ import org.springframework.util.ReflectionUtils;
* {@link GenericArrayType#getGenericComponentType()}) will be automatically wrapped.
*
* @author Phillip Webb
* @author Juergen Hoeller
* @since 4.0
*/
abstract class SerializableTypeWrapper {
@ -210,7 +211,7 @@ abstract class SerializableTypeWrapper { @@ -210,7 +211,7 @@ abstract class SerializableTypeWrapper {
/**
* {@link Serializable} {@link InvocationHandler} used by the Proxied {@link Type}.
* {@link Serializable} {@link InvocationHandler} used by the proxied {@link Type}.
* Provides serialization support and enhances any methods that return {@code Type}
* or {@code Type[]}.
*/
@ -373,21 +374,27 @@ abstract class SerializableTypeWrapper { @@ -373,21 +374,27 @@ abstract class SerializableTypeWrapper {
private final int index;
private transient Object result;
private transient Method method;
private transient volatile Object result;
public MethodInvokeTypeProvider(TypeProvider provider, Method method, int index) {
this.provider = provider;
this.methodName = method.getName();
this.index = index;
this.result = ReflectionUtils.invokeMethod(method, provider.getType());
this.method = method;
}
@Override
public Type getType() {
if (this.result instanceof Type || this.result == null) {
return (Type) this.result;
Object result = this.result;
if (result == null) {
// Lazy invocation of the target method
result = ReflectionUtils.invokeMethod(this.method, this.provider.getType());
// Cache the result for further calls
this.result = result;
}
return ((Type[])this.result)[this.index];
return (result instanceof Type[] ? ((Type[]) result)[this.index] : (Type) result);
}
@Override
@ -397,8 +404,8 @@ abstract class SerializableTypeWrapper { @@ -397,8 +404,8 @@ abstract class SerializableTypeWrapper {
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
Method method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
this.result = ReflectionUtils.invokeMethod(method, this.provider.getType());
this.method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
Assert.state(this.method.getReturnType() == Type.class || this.method.getReturnType() == Type[].class);
}
}

Loading…
Cancel
Save