Author: markt Date: Fri Apr 25 13:49:02 2014 New Revision: 1590028 URL: http://svn.apache.org/r1590028 Log: Defensive coding around some XML activities that are triggered by web applications and are therefore at potential risk of a memory leak.
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java tomcat/tc7.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1589837,1589980 Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java?rev=1590028&r1=1590027&r2=1590028&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/servlets/DefaultServlet.java Fri Apr 25 13:49:02 2014 @@ -32,6 +32,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; @@ -74,6 +75,8 @@ import org.apache.naming.resources.Proxy import org.apache.naming.resources.Resource; import org.apache.naming.resources.ResourceAttributes; 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; @@ -1367,11 +1370,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); @@ -1384,6 +1403,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/tc7.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java?rev=1590028&r1=1590027&r2=1590028&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/jasper/compiler/JspDocumentParser.java Fri Apr 25 13:49:02 2014 @@ -20,6 +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; @@ -35,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; @@ -1464,33 +1467,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/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1590028&r1=1590027&r2=1590028&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Fri Apr 25 13:49:02 2014 @@ -116,6 +116,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