From a7ef51cf300c182ca6a54283bb311d5a69295615 Mon Sep 17 00:00:00 2001 From: Kamil Krzywanski Date: Fri, 6 Jun 2025 21:23:02 +0200 Subject: [PATCH 1/2] Refactor StatusLogger to use precompiled Pattern constants --- .../logging/log4j/status/StatusLogger.java | 65 +++++++++++++++---- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java index 699dc66c8a7..63a59c9b552 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java @@ -39,6 +39,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.regex.Pattern; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; @@ -209,6 +210,44 @@ public class StatusLogger extends AbstractLogger { */ public static final String PROPERTIES_FILE_NAME = "log4j2.StatusLogger.properties"; + /** + * Pattern that matches common separators in property names: + * + *

+ * These are removed during normalization. + *

+ */ + private static final Pattern SEPARATORS = Pattern.compile("[._-]"); + + /** + * Pattern that matches any character not in the ASCII Basic Latin block. + *

+ * These characters are replaced with dots during normalization to avoid mismatches + * while preserving boundaries, e.g. {@code fooàö} becomes {@code foo..}. + *

+ */ + private static final Pattern NON_ASCII = Pattern.compile("\\P{InBasic_Latin}"); + + /** + * Pattern that matches the {@code log4j2} prefix at the start of the property name. + *

+ * This is replaced with {@code log4j} for internal normalization. + *

+ */ + private static final Pattern PREFIX_LOG4J2 = Pattern.compile("^log4j2"); + + /** + * Pattern that matches property names starting with {@code log4j}, case-insensitively. + *

+ * Used to determine if a given property name is relevant for Log4j configuration. + *

+ */ + private static final Pattern LOG4J_PREFIX = Pattern.compile("^log4j.*", Pattern.CASE_INSENSITIVE); + /** * Holder for user-provided {@link StatusLogger} configurations. * @@ -462,7 +501,7 @@ private static Map normalizeProperties(Properties... propertiesL * @return {@code true}, if the property name is relevant; {@code false}, otherwise */ private static boolean isRelevantPropertyName(@Nullable final Object propertyName) { - return propertyName instanceof String && ((String) propertyName).matches("^(?i)log4j.*"); + return propertyName instanceof String && LOG4J_PREFIX.matcher((String) propertyName).matches(); } /** @@ -476,19 +515,17 @@ private static boolean isRelevantPropertyName(@Nullable final Object propertyNam * @return the normalized property name */ private static String normalizePropertyName(final String propertyName) { - return propertyName - // Remove separators: - // - dots (properties) - // - dashes (kebab-case) - // - underscores (environment variables) - .replaceAll("[._-]", "") - // Replace all non-ASCII characters. - // Don't remove, otherwise `fooàö` would incorrectly match with `foo`. - // It is safe to replace them with dots, since we've just removed all dots above. - .replaceAll("\\P{InBasic_Latin}", ".") - // Lowercase ASCII – this is safe, since we've just removed all non-ASCII - .toLowerCase(Locale.US) - .replaceAll("^log4j2", "log4j"); + if (propertyName == null) { + return null; + } + + String propertyNameInput = propertyName; + propertyNameInput = SEPARATORS.matcher(propertyNameInput).replaceAll(""); + propertyNameInput = NON_ASCII.matcher(propertyNameInput).replaceAll("."); + propertyNameInput = propertyNameInput.toLowerCase(Locale.US); + propertyNameInput = PREFIX_LOG4J2.matcher(propertyNameInput).replaceFirst("log4j"); + + return propertyNameInput; } } From 3e89bf9579d988cfd0e55f832b422d7305dd214e Mon Sep 17 00:00:00 2001 From: Kamil Krzywanski Date: Fri, 6 Jun 2025 21:24:39 +0200 Subject: [PATCH 2/2] Refactor StatusLogger to use precompiled Pattern constants --- .../java/org/apache/logging/log4j/status/StatusLogger.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java index 63a59c9b552..b73fdc80752 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java @@ -501,7 +501,8 @@ private static Map normalizeProperties(Properties... propertiesL * @return {@code true}, if the property name is relevant; {@code false}, otherwise */ private static boolean isRelevantPropertyName(@Nullable final Object propertyName) { - return propertyName instanceof String && LOG4J_PREFIX.matcher((String) propertyName).matches(); + return propertyName instanceof String + && LOG4J_PREFIX.matcher((String) propertyName).matches(); } /**