mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Only allow binder recursion with Maps
Refine the binder recursion rules introduced in commit f337323819
so
they only apply to Maps. Recursive List and Array binding is now no
longer allowed. Prior to this commit, binding a List that contained a
reference to itself would fail with a `StackOverflowException` if the
underlying property source was not iterable.
Fixes gh-10702
This commit is contained in:
parent
99ad79dbe6
commit
588dcf76c6
@ -31,8 +31,15 @@ abstract class AggregateBinder<T> {
|
||||
|
||||
private final BindContext context;
|
||||
|
||||
AggregateBinder(BindContext context) {
|
||||
private final boolean allowRecursiveBinding;
|
||||
|
||||
AggregateBinder(BindContext context, boolean allowRecursiveBinding) {
|
||||
this.context = context;
|
||||
this.allowRecursiveBinding = allowRecursiveBinding;
|
||||
}
|
||||
|
||||
boolean isAllowRecursiveBinding() {
|
||||
return this.allowRecursiveBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,13 +188,14 @@ public class Binder {
|
||||
}
|
||||
|
||||
protected final <T> T bind(ConfigurationPropertyName name, Bindable<T> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean) {
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding) {
|
||||
context.clearConfigurationProperty();
|
||||
try {
|
||||
if (!handler.onStart(name, target, context)) {
|
||||
return null;
|
||||
}
|
||||
Object bound = bindObject(name, target, handler, context, skipIfHasBoundBean);
|
||||
Object bound = bindObject(name, target, handler, context,
|
||||
allowRecursiveBinding);
|
||||
return handleBindResult(name, target, handler, context, bound);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@ -232,7 +233,7 @@ public class Binder {
|
||||
}
|
||||
|
||||
private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean)
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding)
|
||||
throws Exception {
|
||||
ConfigurationProperty property = findProperty(name, context);
|
||||
if (property == null && containsNoDescendantOf(context.streamSources(), name)) {
|
||||
@ -245,7 +246,7 @@ public class Binder {
|
||||
if (property != null) {
|
||||
return bindProperty(name, target, handler, context, property);
|
||||
}
|
||||
return bindBean(name, target, handler, context, skipIfHasBoundBean);
|
||||
return bindBean(name, target, handler, context, allowRecursiveBinding);
|
||||
}
|
||||
|
||||
private AggregateBinder<?> getAggregateBinder(Bindable<?> target, Context context) {
|
||||
@ -266,7 +267,7 @@ public class Binder {
|
||||
BindHandler handler, Context context, AggregateBinder<?> aggregateBinder) {
|
||||
AggregateElementBinder elementBinder = (itemName, itemTarget, source) -> {
|
||||
Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context,
|
||||
false);
|
||||
aggregateBinder.isAllowRecursiveBinding());
|
||||
return context.withSource(source, supplier);
|
||||
};
|
||||
return context.withIncreasedDepth(
|
||||
@ -290,15 +291,15 @@ public class Binder {
|
||||
}
|
||||
|
||||
private Object bindBean(ConfigurationPropertyName name, Bindable<?> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean) {
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding) {
|
||||
if (containsNoDescendantOf(context.streamSources(), name)
|
||||
|| isUnbindableBean(name, target, context)) {
|
||||
return null;
|
||||
}
|
||||
BeanPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(
|
||||
name.append(propertyName), propertyTarget, handler, context, true);
|
||||
name.append(propertyName), propertyTarget, handler, context, false);
|
||||
Class<?> type = target.getType().resolve();
|
||||
if (skipIfHasBoundBean && context.hasBoundBean(type)) {
|
||||
if (!allowRecursiveBinding && context.hasBoundBean(type)) {
|
||||
return null;
|
||||
}
|
||||
return context.withBean(type, () -> {
|
||||
|
@ -45,7 +45,7 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
||||
private static final String INDEX_ZERO = "[0]";
|
||||
|
||||
IndexedElementsBinder(BindContext context) {
|
||||
super(context);
|
||||
super(context, false);
|
||||
}
|
||||
|
||||
protected final void bindIndexed(ConfigurationPropertyName name, Bindable<?> target,
|
||||
|
@ -41,7 +41,7 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
|
||||
.mapOf(String.class, String.class);
|
||||
|
||||
MapBinder(BindContext context) {
|
||||
super(context);
|
||||
super(context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user