DATACMNS-1264 - MapDataBinder now rejects improper property expressions.

We now make sure that type expressions cannot be used in SpEL expressions handled by MapDataBinder. They're gonna be rejected by considering the property not writable. SpEL expression evaluation errors are now forwarded as NotWritablePropertyException to make sure the failure gets handled as if the property referred to doesn't exist.
This commit is contained in:
Oliver Gierke
2018-02-26 21:30:54 +01:00
parent 1667311c93
commit e9c375be44
2 changed files with 36 additions and 2 deletions

View File

@@ -43,6 +43,8 @@ import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.SpelMessage;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -177,6 +179,9 @@ class MapDataBinder extends WebDataBinder {
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new PropertyTraversingMapAccessor(type, conversionService));
context.setTypeConverter(new StandardTypeConverter(conversionService));
context.setTypeLocator(typeName -> {
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
});
context.setRootObject(map);
Expression expression = PARSER.parseExpression(propertyName);
@@ -208,7 +213,11 @@ class MapDataBinder extends WebDataBinder {
value = conversionService.convert(value, TypeDescriptor.forObject(value), typeDescriptor);
}
expression.setValue(context, value);
try {
expression.setValue(context, value);
} catch (SpelEvaluationException o_O) {
throw new NotWritablePropertyException(type, propertyName, "Could not write property!", o_O);
}
}
private boolean conversionRequired(@Nullable Object source, Class<?> targetType) {

View File

@@ -28,8 +28,11 @@ import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.NotWritablePropertyException;
import org.springframework.beans.PropertyValues;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.DefaultFormattingConversionService;
@@ -91,7 +94,29 @@ public class MapDataBinderUnitTests {
MutablePropertyValues values = new MutablePropertyValues();
values.add("somethingWeird", "Value");
assertThat(bind(values)).isEqualTo(Collections.<String, Object> emptyMap());
assertThat(bind(values)).isEqualTo(Collections.emptyMap());
}
@Test // DATACMNS-1264
public void dropsMapExpressionsForCollectionReferences() {
ConfigurablePropertyAccessor accessor = new MapDataBinder(Bar.class, new DefaultFormattingConversionService())
.getPropertyAccessor();
assertThatExceptionOfType(NotWritablePropertyException.class) //
.isThrownBy(() -> accessor.setPropertyValue("fooBar['foo']", null)) //
.withCauseInstanceOf(SpelEvaluationException.class);
}
@Test // DATACMNS-1264
public void rejectsExpressionContainingTypeExpression() {
ConfigurablePropertyAccessor accessor = new MapDataBinder(Bar.class, new DefaultFormattingConversionService())
.getPropertyAccessor();
assertThatExceptionOfType(NotWritablePropertyException.class) //
.isThrownBy(() -> accessor.setPropertyValue("fooBar[T(java.lang.String)]", null)) //
.withCauseInstanceOf(SpelEvaluationException.class);
}
private static Map<String, Object> bind(PropertyValues values) {