File logback-CVE-2026-1225.patch of Package logback
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IADataForComplexProperty.java
@@ -26,6 +26,7 @@ public class IADataForComplexProperty {
final AggregationType aggregationType;
final String complexPropertyName;
private Object nestedComplexProperty;
+ private Class<?> expectedPropertyType;
boolean inError;
public IADataForComplexProperty(PropertySetter parentBean, AggregationType aggregationType, String complexPropertyName) {
@@ -46,6 +47,14 @@ public class IADataForComplexProperty {
return complexPropertyName;
}
+ public Class<?> getExpectedPropertyType() {
+ return expectedPropertyType;
+ }
+
+ public void setExpectedPropertyType(Class<?> expectedPropertyType) {
+ this.expectedPropertyType = expectedPropertyType;
+ }
+
public void setNestedComplexProperty(Object nestedComplexProperty) {
this.nestedComplexProperty = nestedComplexProperty;
}
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
@@ -76,7 +76,9 @@ public class NestedComplexPropertyIA extends ImplicitAction {
// we only push action data if NestComponentIA is applicable
case AS_COMPLEX_PROPERTY_COLLECTION:
case AS_COMPLEX_PROPERTY:
+ Class<?> propertyType = parentBean.getTypeForComplexProperty(nestedElementTagName, aggregationType);
IADataForComplexProperty ad = new IADataForComplexProperty(parentBean, aggregationType, nestedElementTagName);
+ ad.setExpectedPropertyType(propertyType);
actionDataStack.push(ad);
return true;
@@ -118,7 +120,11 @@ public class NestedComplexPropertyIA extends ImplicitAction {
addInfo("Assuming default type [" + componentClass.getName() + "] for [" + localName + "] property");
}
- actionData.setNestedComplexProperty(componentClass.newInstance());
+ Class<?> expectedPropertyType = actionData.getExpectedPropertyType();
+
+ Object object = OptionHelper.instantiateClassWithSuperclassRestriction(componentClass, expectedPropertyType);
+
+ actionData.setNestedComplexProperty(object);
// pass along the repository
if (actionData.getNestedComplexProperty() instanceof ContextAware) {
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java
@@ -395,4 +395,36 @@ public class PropertySetter extends ContextAwareBase {
return getByConcreteType(name, relevantMethod);
}
+ public Class<?> getTypeForComplexProperty(String nestedElementTagName, AggregationType aggregationType) {
+
+ Method aMethod = null;
+ switch (aggregationType) {
+ case AS_COMPLEX_PROPERTY:
+ aMethod = findSetterMethod(nestedElementTagName);
+ break;
+ case AS_COMPLEX_PROPERTY_COLLECTION:
+ aMethod = findAdderMethod(nestedElementTagName);
+ }
+
+
+ checkParameterCount(aMethod, nestedElementTagName);
+
+ Class<?>[] paramTypes = aMethod.getParameterTypes();
+ return paramTypes[0];
+
+ }
+
+ private void checkParameterCount(Method aMethod, String nestedElementTagName) {
+ if(aMethod == null) {
+ String msg = "Could not find method for property [" + nestedElementTagName + "].";
+ addError(msg);
+ throw new IllegalStateException(msg);
+ }
+ int parameterCount = aMethod.getParameterCount();
+ if (parameterCount != 1) {
+ String msg = "Expected ["+aMethod.getName()+"] for property [" + nestedElementTagName + "] to have exactly one parameter.";
+ addError(msg);
+ throw new IllegalStateException(msg);
+ }
+ }
}
--- a/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/util/OptionHelper.java
@@ -14,6 +14,7 @@
package ch.qos.logback.core.util;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
import ch.qos.logback.core.Context;
@@ -44,6 +45,19 @@ public class OptionHelper {
return instantiateByClassNameAndParameter(className, superClass, classLoader, null, null);
}
+ public static Object instantiateClassWithSuperclassRestriction(Class<?> classObj, Class<?> superClass)
+ throws IncompatibleClassException, DynamicClassLoadingException {
+ if (!superClass.isAssignableFrom(classObj)) {
+ throw new IncompatibleClassException(superClass, classObj);
+ }
+
+ try {
+ return classObj.getConstructor().newInstance();
+ } catch (NoSuchMethodException|InstantiationException|IllegalAccessException|InvocationTargetException e) {
+ throw new DynamicClassLoadingException("Failed to instantiate type " + classObj.getName(), e);
+ }
+ }
+
public static Object instantiateByClassNameAndParameter(String className, Class<?> superClass, ClassLoader classLoader, Class<?> type, Object parameter)
throws IncompatibleClassException, DynamicClassLoadingException {