You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2021/12/31 23:28:28 UTC

[logging-log4j2] branch LOG4J2-3301 updated: LOG4J2-3301 - Prevent OptionConverter from recursing endlessly

This is an automated email from the ASF dual-hosted git repository.

rgoers pushed a commit to branch LOG4J2-3301
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/LOG4J2-3301 by this push:
     new 2cabcee  LOG4J2-3301 - Prevent OptionConverter from recursing endlessly
2cabcee is described below

commit 2cabceeb1f8f1b8efd64da3ef4a7ed8578685329
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Fri Dec 31 16:28:15 2021 -0700

    LOG4J2-3301 - Prevent OptionConverter from recursing endlessly
---
 .../org/apache/log4j/helpers/OptionConverter.java  | 63 +++++++++++++++++++++-
 src/changes/changes.xml                            |  4 ++
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
index 4044668..62f1f69 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
@@ -25,11 +25,15 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.util.LoaderUtil;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.Strings;
 
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
 /**
@@ -296,7 +300,64 @@ public class OptionConverter {
      * @throws IllegalArgumentException if <code>val</code> is malformed.
      */
     public static String substVars(String val, Properties props) throws IllegalArgumentException {
-        return StrSubstitutor.replace(val, props);
+        return substVars(val, props, new ArrayList<>());
+    }
+
+    private static String substVars(final String val, final Properties props, List<String> keys)
+            throws IllegalArgumentException {
+
+        final StringBuilder sbuf = new StringBuilder();
+
+        int i = 0;
+        int j;
+        int k;
+
+        while (true) {
+            j = val.indexOf(DELIM_START, i);
+            if (j == -1) {
+                // no more variables
+                if (i == 0) { // this is a simple string
+                    return val;
+                }
+                // add the tail string which contails no variables and return the result.
+                sbuf.append(val.substring(i, val.length()));
+                return sbuf.toString();
+            }
+            sbuf.append(val.substring(i, j));
+            k = val.indexOf(DELIM_STOP, j);
+            if (k == -1) {
+                throw new IllegalArgumentException(Strings.dquote(val)
+                        + " has no closing brace. Opening brace at position " + j
+                        + '.');
+            }
+            j += DELIM_START_LEN;
+            final String key = val.substring(j, k);
+            // first try in System properties
+            String replacement = PropertiesUtil.getProperties().getStringProperty(key, null);
+            // then try props parameter
+            if (replacement == null && props != null) {
+                replacement = props.getProperty(key);
+            }
+
+            if (replacement != null) {
+
+                // Do variable substitution on the replacement string
+                // such that we can solve "Hello ${x2}" as "Hello p1"
+                // the where the properties are
+                // x1=p1
+                // x2=${x1}
+                if (!keys.contains(key)) {
+                    List<String> usedKeys = new ArrayList<>(keys);
+                    usedKeys.add(key);
+                    final String recursiveReplacement = substVars(replacement, props, usedKeys);
+                    sbuf.append(recursiveReplacement);
+                } else {
+                    sbuf.append(replacement);
+                }
+
+            }
+            i = k + DELIM_STOP_LEN;
+        }
     }
 
     public static org.apache.logging.log4j.Level convertLevel(String level,
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6989a12..191b8b7 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,10 +30,14 @@
          - "remove" - Removed
     -->
     <release version="2.17.2" date="20YY-MM-DD" description="GA Release 2.17.2">
+
       <action issue="LOG4J2-3267" dev="rpopma" type="update">
         Change modifier of method org.apache.logging.log4j.core.tools.Generate#generate to public (was package private) to facilitate automated code generation.
       </action>
       <!-- FIXES -->
+      <action issue="LOG4J2-3301" dev="rgoers" type="fix">
+        OptionConverter could cause a StackOverflowError.
+      </action>
       <action dev="ggregory" type="fix">
         Log4j 1.2 bridge class ConsoleAppender should extend WriterAppender and provide better compatibility with custom appenders.
       </action>