You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/10/28 22:51:02 UTC

svn commit: r1403099 - in /tomcat/trunk: java/org/apache/jasper/runtime/PageContextImpl.java test/org/apache/jasper/runtime/TesterPageContextImpl.java

Author: markt
Date: Sun Oct 28 21:51:02 2012
New Revision: 1403099

URL: http://svn.apache.org/viewvc?rev=1403099&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53867
Improve performance of XML escaping
Based on a patch by Sheldon Shao

Added:
    tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java

Modified: tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java?rev=1403099&r1=1403098&r2=1403099&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java (original)
+++ tomcat/trunk/java/org/apache/jasper/runtime/PageContextImpl.java Sun Oct 28 21:51:02 2012
@@ -902,27 +902,67 @@ public class PageContextImpl extends Pag
         }
     }
 
-    private static String XmlEscape(String s) {
-        if (s == null)
+    protected static String XmlEscape(String s) {
+        if (s == null) {
             return null;
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < s.length(); i++) {
+        }
+        int len = s.length();
+
+        /*
+         * Look for any "bad" characters, Escape "bad" character was found
+         */
+        // ASCII " 34 & 38 ' 39 < 60 > 62
+        for (int i = 0; i < len; i++) {
             char c = s.charAt(i);
-            if (c == '<') {
-                sb.append("&lt;");
-            } else if (c == '>') {
-                sb.append("&gt;");
-            } else if (c == '\'') {
-                sb.append("&#039;"); // &apos;
-            } else if (c == '&') {
-                sb.append("&amp;");
-            } else if (c == '"') {
-                sb.append("&#034;"); // &quot;
-            } else {
-                sb.append(c);
+            if (c >= '\"' && c <= '>' &&
+                    (c == '<' || c == '>' || c == '\'' || c == '&' || c == '"')) {
+                // need to escape them and then quote the whole string
+                StringBuilder sb = new StringBuilder((int) (len * 1.2));
+                sb.append(s, 0, i);
+                int pos = i + 1;
+                for (int j = i; j < len; j++) {
+                    c = s.charAt(j);
+                    if (c >= '\"' && c <= '>') {
+                        if (c == '<') {
+                            if (j > pos) {
+                                sb.append(s, pos, j);
+                            }
+                            sb.append("&lt;");
+                            pos = j + 1;
+                        } else if (c == '>') {
+                            if (j > pos) {
+                                sb.append(s, pos, j);
+                            }
+                            sb.append("&gt;");
+                            pos = j + 1;
+                        } else if (c == '\'') {
+                            if (j > pos) {
+                                sb.append(s, pos, j);
+                            }
+                            sb.append("&#039;"); // &apos;
+                            pos = j + 1;
+                        } else if (c == '&') {
+                            if (j > pos) {
+                                sb.append(s, pos, j);
+                            }
+                            sb.append("&amp;");
+                            pos = j + 1;
+                        } else if (c == '"') {
+                            if (j > pos) {
+                                sb.append(s, pos, j);
+                            }
+                            sb.append("&#034;"); // &quot;
+                            pos = j + 1;
+                        }
+                    }
+                }
+                if (pos < len) {
+                    sb.append(s, pos, len);
+                }
+                return sb.toString();
             }
         }
-        return sb.toString();
+        return s;
     }
 
     /**

Added: tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java?rev=1403099&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java (added)
+++ tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java Sun Oct 28 21:51:02 2012
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jasper.runtime;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Performance tests for {@link PageContextImpl}.
+ */
+public class TesterPageContextImpl {
+
+    private static String[] bug53867TestData = new String[] {
+            "Hello World!",
+            "<meta http-equiv=\"Content-Language\">",
+            "This connection has limited network connectivity.",
+            "Please use this web page & to access file server resources." };
+
+    @Test
+    public void testBug53867() {
+        for (int i = 0; i < 10; i++) {
+            doTestBug53867();
+        }
+    }
+
+    private static void doTestBug53867() {
+        int count = 100000;
+
+        for (int j = 0; j < bug53867TestData.length; j++) {
+            Assert.assertEquals(doTestBug53867OldVersion(bug53867TestData[j]),
+                    PageContextImpl.XmlEscape(bug53867TestData[j]));
+        }
+
+        for (int i = 0; i < 100; i++) {
+            for (int j = 0; j < bug53867TestData.length; j++) {
+                doTestBug53867OldVersion(bug53867TestData[j]);
+            }
+        }
+        for (int i = 0; i < 100; i++) {
+            for (int j = 0; j < bug53867TestData.length; j++) {
+                PageContextImpl.XmlEscape(bug53867TestData[j]);
+            }
+        }
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < count; i++) {
+            for (int j = 0; j < bug53867TestData.length; j++) {
+                doTestBug53867OldVersion(bug53867TestData[j]);
+            }
+        }
+        System.out.println(
+                "Old escape:" + (System.currentTimeMillis() - start));
+
+        start = System.currentTimeMillis();
+        for (int i = 0; i < count; i++) {
+            for (int j = 0; j < bug53867TestData.length; j++) {
+                PageContextImpl.XmlEscape(bug53867TestData[j]);
+            }
+        }
+        System.out.println(
+                "New escape:" + (System.currentTimeMillis() - start));
+    }
+
+    private static String doTestBug53867OldVersion(String s) {
+        if (s == null)
+            return null;
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '<') {
+                sb.append("&lt;");
+            } else if (c == '>') {
+                sb.append("&gt;");
+            } else if (c == '\'') {
+                sb.append("&#039;"); // &apos;
+            } else if (c == '&') {
+                sb.append("&amp;");
+            } else if (c == '"') {
+                sb.append("&#034;"); // &quot;
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}

Propchange: tomcat/trunk/test/org/apache/jasper/runtime/TesterPageContextImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org