You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2018/07/16 17:51:09 UTC

logging-log4j2 git commit: [LOG4J2-2376] Optimize XML escape functionality and add unit testing.

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 6cfddc9ea -> 59925f963


[LOG4J2-2376] Optimize XML escape functionality and add unit testing.

This closes #192


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/59925f96
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/59925f96
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/59925f96

Branch: refs/heads/master
Commit: 59925f963955d3e727071db740abe203d22ab8dc
Parents: 6cfddc9
Author: kmeurer <km...@palantir.com>
Authored: Mon Jul 16 12:33:57 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Mon Jul 16 13:50:49 2018 -0400

----------------------------------------------------------------------
 .../logging/log4j/util/StringBuilders.java      | 60 ++++++++++++++++----
 .../logging/log4j/util/StringBuildersTest.java  | 12 ++++
 src/changes/changes.xml                         |  8 +++
 3 files changed, 69 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/59925f96/log4j-api/src/main/java/org/apache/logging/log4j/util/StringBuilders.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StringBuilders.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StringBuilders.java
index 2a83b24..48fa98f 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StringBuilders.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StringBuilders.java
@@ -245,29 +245,67 @@ public final class StringBuilders {
     }
 
     public static void escapeXml(final StringBuilder toAppendTo, final int start) {
-        for (int i = toAppendTo.length() - 1; i >= start; i--) { // backwards: length may change
+        int escapeCount = 0;
+        for (int i = start; i < toAppendTo.length(); i++) {
+            final char c = toAppendTo.charAt(i);
+            switch (c) {
+                case '&':
+                    escapeCount += 4;
+                    break;
+                case '<':
+                case '>':
+                    escapeCount += 3;
+                    break;
+                case '"':
+                case '\'':
+                    escapeCount += 5;
+            }
+        }
+
+        int lastChar = toAppendTo.length() - 1;
+        toAppendTo.setLength(toAppendTo.length() + escapeCount);
+        int lastPos = toAppendTo.length() - 1;
+
+        for (int i = lastChar; lastPos > i; i--) {
             final char c = toAppendTo.charAt(i);
             switch (c) {
                 case '&':
-                    toAppendTo.setCharAt(i, '&');
-                    toAppendTo.insert(i + 1, "amp;");
+                    toAppendTo.setCharAt(lastPos--, ';');
+                    toAppendTo.setCharAt(lastPos--, 'p');
+                    toAppendTo.setCharAt(lastPos--, 'm');
+                    toAppendTo.setCharAt(lastPos--, 'a');
+                    toAppendTo.setCharAt(lastPos--, '&');
                     break;
                 case '<':
-                    toAppendTo.setCharAt(i, '&');
-                    toAppendTo.insert(i + 1, "lt;");
+                    toAppendTo.setCharAt(lastPos--, ';');
+                    toAppendTo.setCharAt(lastPos--, 't');
+                    toAppendTo.setCharAt(lastPos--, 'l');
+                    toAppendTo.setCharAt(lastPos--, '&');
                     break;
                 case '>':
-                    toAppendTo.setCharAt(i, '&');
-                    toAppendTo.insert(i + 1, "gt;");
+                    toAppendTo.setCharAt(lastPos--, ';');
+                    toAppendTo.setCharAt(lastPos--, 't');
+                    toAppendTo.setCharAt(lastPos--, 'g');
+                    toAppendTo.setCharAt(lastPos--, '&');
                     break;
                 case '"':
-                    toAppendTo.setCharAt(i, '&');
-                    toAppendTo.insert(i + 1, "quot;");
+                    toAppendTo.setCharAt(lastPos--, ';');
+                    toAppendTo.setCharAt(lastPos--, 't');
+                    toAppendTo.setCharAt(lastPos--, 'o');
+                    toAppendTo.setCharAt(lastPos--, 'u');
+                    toAppendTo.setCharAt(lastPos--, 'q');
+                    toAppendTo.setCharAt(lastPos--, '&');
                     break;
                 case '\'':
-                    toAppendTo.setCharAt(i, '&');
-                    toAppendTo.insert(i + 1, "apos;");
+                    toAppendTo.setCharAt(lastPos--, ';');
+                    toAppendTo.setCharAt(lastPos--, 's');
+                    toAppendTo.setCharAt(lastPos--, 'o');
+                    toAppendTo.setCharAt(lastPos--, 'p');
+                    toAppendTo.setCharAt(lastPos--, 'a');
+                    toAppendTo.setCharAt(lastPos--, '&');
                     break;
+                default:
+                    toAppendTo.setCharAt(lastPos--, c);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/59925f96/log4j-api/src/test/java/org/apache/logging/log4j/util/StringBuildersTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/util/StringBuildersTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/util/StringBuildersTest.java
index 7c74073..6feecbb 100644
--- a/log4j-api/src/test/java/org/apache/logging/log4j/util/StringBuildersTest.java
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/util/StringBuildersTest.java
@@ -77,4 +77,16 @@ public class StringBuildersTest {
         StringBuilders.escapeJson(sb, 0);
         assertEquals(jsonValueEscaped, sb.toString());
     }
+
+    @Test
+    public void escapeXMLCharactersCorrectly() {
+        String xmlValueNotEscaped = "<\"Salt&Peppa'\">";
+        String xmlValueEscaped = "&lt;&quot;Salt&amp;Peppa&apos;&quot;&gt;";
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(xmlValueNotEscaped);
+        assertEquals(xmlValueNotEscaped, sb.toString());
+        StringBuilders.escapeXml(sb, 0);
+        assertEquals(xmlValueEscaped, sb.toString());
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/59925f96/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 852335e..0fa496d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -211,6 +211,10 @@
         StringBuilders.escapeJson implementation runs in linear time. Escaping large JSON strings
         in EncodingPatternConverter and MapMessage will perform significantly better.
       </action>
+      <action issue="LOG4J2-2376" dev="ckozak" type="fix" due-to="Kevin Meurer">
+        StringBuilders.escapeXml implementation runs in linear time. Escaping large XML strings
+        in EncodingPatternConverter and MapMessage will perform significantly better.
+      </action>
     </release>
     <release version="2.11.1" date="2018-MM-DD" description="GA Release 2.11.1">
       <action issue="LOG4J2-1721" dev="rgoers" type="update" due-to="Phokham Nonava">
@@ -330,6 +334,10 @@
         StringBuilders.escapeJson implementation runs in linear time. Escaping large JSON strings
         in EncodingPatternConverter and MapMessage will perform significantly better.
       </action>
+      <action issue="LOG4J2-2376" dev="ckozak" type="fix" due-to="Kevin Meurer">
+        StringBuilders.escapeXml implementation runs in linear time. Escaping large XML strings
+        in EncodingPatternConverter and MapMessage will perform significantly better.
+      </action>
     </release>
     <release version="2.11.0" date="2018-xx-xx" description="GA Release 2.11.0">
       <action issue="LOG4J2-2104" dev="rgoers" type="fix">