Author: markt Date: Thu Apr 24 19:16:21 2014 New Revision: 1589837 URL: http://svn.apache.org/r1589837 Log: Add some defensive coding around some XML activities that are triggered by web applications and are therefore at potential risk of a memory leak.
Modified: tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java tomcat/trunk/res/checkstyle/org-import-control.xml tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java?rev=1589837&r1=1589836&r2=1589837&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java (original) +++ tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java Thu Apr 24 19:16:21 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.Enumeration; import java.util.Iterator; @@ -68,6 +69,8 @@ import org.apache.catalina.util.RequestU import org.apache.catalina.util.ServerInfo; import org.apache.catalina.util.URLEncoder; import org.apache.tomcat.util.res.StringManager; +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; @@ -1309,11 +1312,27 @@ public class DefaultServlet extends Http 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); @@ -1326,6 +1345,13 @@ public class DefaultServlet extends Http 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/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java?rev=1589837&r1=1589836&r2=1589837&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java Thu Apr 24 19:16:21 2014 @@ -19,6 +19,7 @@ package org.apache.jasper.compiler; import java.io.CharArrayWriter; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.AccessController; import java.util.Collection; import java.util.Iterator; @@ -35,6 +36,8 @@ import org.apache.tomcat.util.descriptor import org.apache.tomcat.util.descriptor.LocalResolver; import org.apache.tomcat.util.descriptor.tld.TldResourcePath; import org.apache.tomcat.util.scan.Jar; +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; @@ -1452,33 +1455,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/trunk/res/checkstyle/org-import-control.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/res/checkstyle/org-import-control.xml?rev=1589837&r1=1589836&r2=1589837&view=diff ============================================================================== --- tomcat/trunk/res/checkstyle/org-import-control.xml (original) +++ tomcat/trunk/res/checkstyle/org-import-control.xml Thu Apr 24 19:16:21 2014 @@ -102,6 +102,7 @@ <allow pkg="org.apache.tomcat" exact-match="true"/> <allow pkg="org.apache.tomcat.util.descriptor"/> <allow pkg="org.apache.tomcat.util.scan"/> + <allow pkg="org.apache.tomcat.util.security"/> <allow pkg="org.apache.tools.ant"/> <allow pkg="org.eclipse.jdt"/> </subpackage> Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1589837&r1=1589836&r2=1589837&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Apr 24 19:16:21 2014 @@ -131,6 +131,11 @@ patterns of the form <code>*.a.b</code> which are not valid patterns for extension mappings. (markt) </add> + <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