Author: kkolinko
Date: Sun May 11 17:15:52 2014
New Revision: 1593821

URL: http://svn.apache.org/r1593821
Log:
Defensive coding around some XML activities that are triggered by web
applications and are therefore at potential risk of a memory leak.
Patch by markt.

Added:
    tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/
      - copied from r1593818, 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/security/
Modified:
    tomcat/tc6.0.x/trunk/STATUS.txt
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/session/StandardSession.java
    tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java
    tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java
    tomcat/tc6.0.x/trunk/java/org/apache/jasper/xmlparser/ParserUtils.java
    
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
    
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
    tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml

Modified: tomcat/tc6.0.x/trunk/STATUS.txt
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/STATUS.txt (original)
+++ tomcat/tc6.0.x/trunk/STATUS.txt Sun May 11 17:15:52 2014
@@ -28,12 +28,6 @@ None
 PATCHES PROPOSED TO BACKPORT:
   [ New proposals should be added at the end of the list ]
 
-* Defensive coding around some XML activities that are triggered by web
-  applications and are therefore at potential risk of a memory leak.
-  http://people.apache.org/~markt/patches/2014-04-25-memory-leak-tc6-v1.patch
-  +1: markt, kkolinko, fhanik
-  -1:
-
 * Followup to r1589635
   To simplify code and align it with TC7 & 8.
   (Discussed in Re:r1589635)

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/security/SecurityClassLoad.java 
(original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/security/SecurityClassLoad.java 
Sun May 11 17:15:52 2014
@@ -96,17 +96,10 @@ public final class SecurityClassLoad {
 
     private final static void loadSessionPackage(ClassLoader loader)
         throws Exception {
-        String basePackage = "org.apache.catalina.";
-        loader.loadClass
-            (basePackage + "session.StandardSession");
-        loader.loadClass
-            (basePackage + "session.StandardSession$PrivilegedSetTccl");
-        loader.loadClass
-            (basePackage +
-             "session.StandardSession$1");
-        loader.loadClass
-            (basePackage +
-             "session.StandardManager$PrivilegedDoUnload");
+        String basePackage = "org.apache.catalina.session.";
+        loader.loadClass(basePackage + "StandardSession");
+        loader.loadClass(basePackage + "StandardSession$1");
+        loader.loadClass(basePackage + "StandardManager$PrivilegedDoUnload");
     }
     
     
@@ -229,6 +222,10 @@ public final class SecurityClassLoad {
         Class<?> clazz = loader.loadClass(
                 basePackage + "util.http.FastHttpDateFormat");
         clazz.newInstance();
+
+        // security
+        loader.loadClass(basePackage + "util.security.PrivilegedGetTccl");
+        loader.loadClass(basePackage + "util.security.PrivilegedSetTccl");
     }
 }
 

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java 
Sun May 11 17:15:52 2014
@@ -31,6 +31,7 @@ import java.io.RandomAccessFile;
 import java.io.Reader;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Locale;
@@ -68,6 +69,8 @@ import org.apache.naming.resources.Cache
 import org.apache.naming.resources.ProxyDirContext;
 import org.apache.naming.resources.Resource;
 import org.apache.naming.resources.ResourceAttributes;
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
 import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -1326,11 +1329,27 @@ public class DefaultServlet
             sb.append("]]></readme>");
         }
 
-
         sb.append("</listing>");
 
-
+        // Prevent possible memory leak. Ensure Transformer and
+        // TransformerFactory are not loaded from the web application.
+        ClassLoader original;
+        if (Globals.IS_SECURITY_ENABLED) {
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
+            original = AccessController.doPrivileged(pa);
+        } else {
+            original = Thread.currentThread().getContextClassLoader();
+        }
         try {
+            if (Globals.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa =
+                        new 
PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(
+                        DefaultServlet.class.getClassLoader());
+            }
+
             TransformerFactory tFactory = TransformerFactory.newInstance();
             Source xmlSource = new StreamSource(new 
StringReader(sb.toString()));
             Transformer transformer = tFactory.newTransformer(xsltSource);
@@ -1343,6 +1362,13 @@ public class DefaultServlet
             return (new ByteArrayInputStream(stream.toByteArray()));
         } catch (TransformerException e) {
             throw new ServletException("XSL transformer error", e);
+        } finally {
+            if (Globals.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(original);
+            }
         }
     }
 

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/session/StandardSession.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/session/StandardSession.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/session/StandardSession.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/session/StandardSession.java 
Sun May 11 17:15:52 2014
@@ -60,6 +60,7 @@ import org.apache.catalina.core.Standard
 import org.apache.catalina.realm.GenericPrincipal;
 import org.apache.catalina.security.SecurityUtil;
 import org.apache.catalina.session.ManagerBase.SessionTiming;
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
 
 /**
  * Standard implementation of the <b>Session</b> interface.  This object is
@@ -1744,28 +1745,9 @@ public class StandardSession
                     (sm.getString("standardSession.attributeEvent"), t);
             }
         }
-
     }
-
-
-    private static class PrivilegedSetTccl
-    implements PrivilegedAction<Void> {
-
-        private ClassLoader cl;
-
-        PrivilegedSetTccl(ClassLoader cl) {
-            this.cl = cl;
-        }
-
-        public Void run() {
-            Thread.currentThread().setContextClassLoader(cl);
-            return null;
-        }
-    }
-
 }
 
-
 // ------------------------------------------------------------ Protected Class
 
 

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java 
Sun May 11 17:15:52 2014
@@ -24,6 +24,7 @@ import javax.servlet.jsp.tagext.Function
 
 import org.apache.jasper.Constants;
 import org.apache.jasper.JasperException;
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
 
 /**
  * This class generates functions mappers for the EL expressions in the page.
@@ -307,13 +308,5 @@ public class ELFunctionMapper {
             return clazz.getCanonicalName();
         }
     }
-    
-    private static class PrivilegedGetTccl
-            implements PrivilegedAction<ClassLoader> {
-
-        public ClassLoader run() {
-            return Thread.currentThread().getContextClassLoader();
-        }
-    }
 }
 

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java 
Sun May 11 17:15:52 2014
@@ -20,7 +20,7 @@ import java.io.CharArrayWriter;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-
+import java.security.AccessController;
 import java.util.Iterator;
 import java.util.List;
 import java.util.jar.JarFile;
@@ -36,6 +36,8 @@ import org.apache.jasper.JasperException
 import org.apache.jasper.JspCompilationContext;
 import org.apache.tomcat.util.descriptor.DigesterFactory;
 import org.apache.tomcat.util.descriptor.LocalResolver;
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.Locator;
@@ -1454,33 +1456,58 @@ class JspDocumentParser
         JspDocumentParser jspDocParser)
         throws Exception {
 
-        SAXParserFactory factory = SAXParserFactory.newInstance();
-
-        factory.setNamespaceAware(true);
-        // Preserve xmlns attributes
-        factory.setFeature(
-            "http://xml.org/sax/features/namespace-prefixes";,
-            true);
-
-        factory.setValidating(validating);
-        if (validating) {
-            // Enable DTD validation
-            factory.setFeature(
-                    "http://xml.org/sax/features/validation";,
-                    true);
-            // Enable schema validation
-            factory.setFeature(
-                    "http://apache.org/xml/features/validation/schema";,
-                    true);
+        ClassLoader original;
+        if (Constants.IS_SECURITY_ENABLED) {
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
+            original = AccessController.doPrivileged(pa);
+        } else {
+            original = Thread.currentThread().getContextClassLoader();
         }
+        try {
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa =
+                        new 
PrivilegedSetTccl(JspDocumentParser.class.getClassLoader());
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(
+                        JspDocumentParser.class.getClassLoader());
+            }
+
+            SAXParserFactory factory = SAXParserFactory.newInstance();
 
-        // Configure the parser
-        SAXParser saxParser = factory.newSAXParser();
-        XMLReader xmlReader = saxParser.getXMLReader();
-        xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
-        xmlReader.setErrorHandler(jspDocParser);
+            factory.setNamespaceAware(true);
+            // Preserve xmlns attributes
+            factory.setFeature(
+                "http://xml.org/sax/features/namespace-prefixes";,
+                true);
 
-        return saxParser;
+            factory.setValidating(validating);
+            if (validating) {
+                // Enable DTD validation
+                factory.setFeature(
+                        "http://xml.org/sax/features/validation";,
+                        true);
+                // Enable schema validation
+                factory.setFeature(
+                        "http://apache.org/xml/features/validation/schema";,
+                        true);
+            }
+
+            // Configure the parser
+            SAXParser saxParser = factory.newSAXParser();
+            XMLReader xmlReader = saxParser.getXMLReader();
+            xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
+            xmlReader.setErrorHandler(jspDocParser);
+
+            return saxParser;
+        } finally {
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(original);
+            }
+        }
     }
 
     /*

Modified: tomcat/tc6.0.x/trunk/java/org/apache/jasper/xmlparser/ParserUtils.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/jasper/xmlparser/ParserUtils.java?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/jasper/xmlparser/ParserUtils.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/jasper/xmlparser/ParserUtils.java Sun 
May 11 17:15:52 2014
@@ -18,6 +18,7 @@ package org.apache.jasper.xmlparser;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.security.AccessController;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -29,6 +30,8 @@ import org.apache.jasper.compiler.Locali
 import org.apache.tomcat.util.descriptor.DigesterFactory;
 import org.apache.tomcat.util.descriptor.LocalResolver;
 import org.apache.tomcat.util.descriptor.XmlErrorHandler;
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
 import org.w3c.dom.Comment;
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
@@ -105,7 +108,23 @@ public class ParserUtils {
         Document document = null;
 
         // Perform an XML parse of this document, via JAXP
+        ClassLoader original;
+        if (Constants.IS_SECURITY_ENABLED) {
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
+            original = AccessController.doPrivileged(pa);
+        } else {
+            original = Thread.currentThread().getContextClassLoader();
+        }
         try {
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa =
+                        new 
PrivilegedSetTccl(ParserUtils.class.getClassLoader());
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(
+                        ParserUtils.class.getClassLoader());
+            }
+            
             DocumentBuilderFactory factory =
                 DocumentBuilderFactory.newInstance();
             factory.setNamespaceAware(true);
@@ -129,23 +148,30 @@ public class ParserUtils {
                 // throw the first to indicate there was a error during 
processing
                 throw handler.getErrors().iterator().next();
             }
-       } catch (ParserConfigurationException ex) {
-            throw new JasperException
-                (Localizer.getMessage("jsp.error.parse.xml", location), ex);
-       } catch (SAXParseException ex) {
-            throw new JasperException
-                (Localizer.getMessage("jsp.error.parse.xml.line",
-                      location,
-                                     Integer.toString(ex.getLineNumber()),
-                                     Integer.toString(ex.getColumnNumber())),
-                ex);
-       } catch (SAXException sx) {
-            throw new JasperException
-                (Localizer.getMessage("jsp.error.parse.xml", location), sx);
+        } catch (ParserConfigurationException ex) {
+            throw new JasperException(
+                    Localizer.getMessage("jsp.error.parse.xml", location), ex);
+        } catch (SAXParseException ex) {
+            throw new JasperException(
+                    Localizer.getMessage("jsp.error.parse.xml.line",
+                            location,
+                            Integer.toString(ex.getLineNumber()),
+                                       Integer.toString(ex.getColumnNumber())),
+                               ex);
+        } catch (SAXException sx) {
+            throw new JasperException(
+                    Localizer.getMessage("jsp.error.parse.xml", location), sx);
         } catch (IOException io) {
-            throw new JasperException
-                (Localizer.getMessage("jsp.error.parse.xml", location), io);
-       }
+            throw new JasperException(
+                    Localizer.getMessage("jsp.error.parse.xml", location), io);
+        } finally {
+            if (Constants.IS_SECURITY_ENABLED) {
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
+                AccessController.doPrivileged(pa);
+            } else {
+                Thread.currentThread().setContextClassLoader(original);
+            }
+        }
 
         // Convert the resulting document to a graph of TreeNodes
         return (convert(null, document.getDocumentElement()));

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java?rev=1593821&r1=1593818&r2=1593821&view=diff
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
 (original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedGetTccl.java
 Sun May 11 17:15:52 2014
@@ -19,7 +19,6 @@ package org.apache.tomcat.util.security;
 import java.security.PrivilegedAction;
 
 public class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {
-    @Override
     public ClassLoader run() {
         return Thread.currentThread().getContextClassLoader();
     }

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java?rev=1593821&r1=1593818&r2=1593821&view=diff
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
 (original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/security/PrivilegedSetTccl.java
 Sun May 11 17:15:52 2014
@@ -26,7 +26,6 @@ public class PrivilegedSetTccl implement
         this.cl = cl;
     }
 
-    @Override
     public Void run() {
         Thread.currentThread().setContextClassLoader(cl);
         return null;

Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1593821&r1=1593820&r2=1593821&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Sun May 11 17:15:52 2014
@@ -99,6 +99,11 @@
         Ensure that a TLD parser obtained from the cache has the correct value
         of <code>blockExternal</code>. (markt/kkolinko)
       </fix>
+      <add>
+        Extend XML factory, parser etc. memory leak protection to cover some
+        additional locations where, theoretically, a memory leak could occur.
+        (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">



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

Reply via email to