Blame SOURCES/tomcat-7.0.42-CVE-2014-0119.patch

f90819
--- java/org/apache/catalina/security/SecurityClassLoad.java.orig	2014-07-24 18:29:38.830023000 -0400
f90819
+++ java/org/apache/catalina/security/SecurityClassLoad.java	2014-07-24 18:31:18.655356000 -0400
f90819
@@ -25,9 +25,7 @@
f90819
  *
f90819
  * @author Glenn L. Nielsen
f90819
  * @author Jean-Francois Arcand
f90819
- * @version $Id: SecurityClassLoad.java 1410548 2012-11-16 19:38:51Z markt $
f90819
  */
f90819
-
f90819
 public final class SecurityClassLoad {
f90819
 
f90819
     public static void securityClassLoad(ClassLoader loader)
f90819
@@ -41,6 +39,7 @@
f90819
         loadCoyotePackage(loader);
f90819
         loadLoaderPackage(loader);
f90819
         loadRealmPackage(loader);
f90819
+        loadServletsPackage(loader);
f90819
         loadSessionPackage(loader);
f90819
         loadUtilPackage(loader);
f90819
         loadValvesPackage(loader);
f90819
@@ -76,12 +75,6 @@
f90819
             "AsyncContextImpl$1");
f90819
         loader.loadClass
f90819
             (basePackage +
f90819
-            "AsyncContextImpl$PrivilegedGetTccl");
f90819
-        loader.loadClass
f90819
-            (basePackage +
f90819
-            "AsyncContextImpl$PrivilegedSetTccl");
f90819
-        loader.loadClass
f90819
-            (basePackage +
f90819
             "AsyncListenerWrapper");
f90819
         loader.loadClass
f90819
             (basePackage +
f90819
@@ -124,14 +117,24 @@
f90819
     }
f90819
 
f90819
 
f90819
+    private static final void loadServletsPackage(ClassLoader loader)
f90819
+            throws Exception {
f90819
+        final String basePackage = "org.apache.catalina.servlets.";
f90819
+        // Avoid a possible memory leak in the DefaultServlet when running with
f90819
+        // a security manager. The DefaultServlet needs to load an XML parser
f90819
+        // when running under a security manager. We want this to be loaded by
f90819
+        // the container rather than a web application to prevent a memory leak
f90819
+        // via web application class loader.
f90819
+        loader.loadClass(basePackage + "DefaultServlet");
f90819
+    }
f90819
+
f90819
+
f90819
     private static final void loadSessionPackage(ClassLoader loader)
f90819
         throws Exception {
f90819
         final String basePackage = "org.apache.catalina.session.";
f90819
         loader.loadClass
f90819
             (basePackage + "StandardSession");
f90819
         loader.loadClass
f90819
-            (basePackage + "StandardSession$PrivilegedSetTccl");
f90819
-        loader.loadClass
f90819
             (basePackage + "StandardSession$1");
f90819
         loader.loadClass
f90819
             (basePackage + "StandardManager$PrivilegedDoUnload");
f90819
@@ -280,10 +283,9 @@
f90819
         loader.loadClass(basePackage +
f90819
                 "util.net.NioBlockingSelector$BlockPoller$3");
f90819
         loader.loadClass(basePackage + "util.net.SSLSupport$CipherData");
f90819
-        loader.loadClass
f90819
-            (basePackage + "util.net.JIoEndpoint$PrivilegedSetTccl");
f90819
-        loader.loadClass
f90819
-            (basePackage + "util.net.AprEndpoint$PrivilegedSetTccl");
f90819
+        // security
f90819
+        loader.loadClass(basePackage + "util.security.PrivilegedGetTccl");
f90819
+        loader.loadClass(basePackage + "util.security.PrivilegedSetTccl");
f90819
     }
f90819
 }
f90819
 
f90819
--- java/org/apache/catalina/servlets/DefaultServlet.java.orig	2014-07-24 18:29:38.875020000 -0400
f90819
+++ java/org/apache/catalina/servlets/DefaultServlet.java	2014-07-24 18:31:18.695352000 -0400
f90819
@@ -14,8 +14,6 @@
f90819
  * See the License for the specific language governing permissions and
f90819
  * limitations under the License.
f90819
  */
f90819
-
f90819
-
f90819
 package org.apache.catalina.servlets;
f90819
 
f90819
 
f90819
@@ -34,6 +32,7 @@
f90819
 import java.io.Reader;
f90819
 import java.io.StringReader;
f90819
 import java.io.StringWriter;
f90819
+import java.security.AccessController;
f90819
 import java.util.ArrayList;
f90819
 import java.util.Iterator;
f90819
 import java.util.Locale;
f90819
@@ -76,11 +75,14 @@
f90819
 import org.apache.naming.resources.Resource;
f90819
 import org.apache.naming.resources.ResourceAttributes;
f90819
 import org.apache.tomcat.util.res.StringManager;
f90819
-
f90819
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
f90819
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
f90819
 import org.w3c.dom.Document;
f90819
 import org.xml.sax.InputSource;
f90819
 import org.xml.sax.SAXException;
f90819
 import org.xml.sax.ext.EntityResolver2;
f90819
+
f90819
+
f90819
 /**
f90819
  * 

The default resource-serving servlet for most web applications,

f90819
  * used to serve static resources such as HTML pages and images.
f90819
@@ -122,9 +124,7 @@
f90819
  * 

f90819
  * @author Craig R. McClanahan
f90819
  * @author Remy Maucherat
f90819
- * @version $Id: DefaultServlet.java 1301255 2012-03-15 22:47:40Z markt $
f90819
  */
f90819
-
f90819
 public class DefaultServlet
f90819
     extends HttpServlet {
f90819
 
f90819
@@ -132,10 +132,10 @@
f90819
 
f90819
     private static final DocumentBuilderFactory factory;
f90819
 
f90819
-    private static final SecureEntityResolver secureEntityResolver =
f90819
-            new SecureEntityResolver();
f90819
-    // ----------------------------------------------------- Instance Variables
f90819
+    private static final SecureEntityResolver secureEntityResolver;
f90819
+
f90819
 
f90819
+    // ----------------------------------------------------- Instance Variables
f90819
 
f90819
     /**
f90819
      * The debugging detail level for this servlet.
f90819
@@ -225,6 +225,11 @@
f90819
      */
f90819
     protected static final ArrayList<Range> FULL = new ArrayList<Range>();
f90819
 
f90819
+    /**
f90819
+     * Flag to determine if server information is presented.
f90819
+     */
f90819
+    protected boolean showServerInfo = true;
f90819
+
f90819
 
f90819
     // ----------------------------------------------------- Static Initializer
f90819
 
f90819
@@ -239,9 +244,16 @@
f90819
         urlEncoder.addSafeCharacter('.');
f90819
         urlEncoder.addSafeCharacter('*');
f90819
         urlEncoder.addSafeCharacter('/');
f90819
-        factory = DocumentBuilderFactory.newInstance();
f90819
-        factory.setNamespaceAware(true);
f90819
-        factory.setValidating(false);
f90819
+        
f90819
+        if (Globals.IS_SECURITY_ENABLED) {
f90819
+            factory = DocumentBuilderFactory.newInstance();
f90819
+            factory.setNamespaceAware(true);
f90819
+            factory.setValidating(false);
f90819
+            secureEntityResolver = new SecureEntityResolver();
f90819
+        } else {
f90819
+            factory = null;
f90819
+            secureEntityResolver = null;
f90819
+        }
f90819
     }
f90819
 
f90819
 
f90819
@@ -270,6 +282,7 @@
f90819
     protected static final int BUFFER_SIZE = 4096;
f90819
 
f90819
 
f90819
+
f90819
     // --------------------------------------------------------- Public Methods
f90819
 
f90819
 
f90819
@@ -345,6 +358,9 @@
f90819
             throw new UnavailableException("No resources");
f90819
         }
f90819
 
f90819
+        if (getServletConfig().getInitParameter("showServerInfo") != null) {
f90819
+            showServerInfo = Boolean.parseBoolean(getServletConfig().getInitParameter("showServerInfo"));
f90819
+        }
f90819
     }
f90819
 
f90819
 
f90819
@@ -1251,7 +1267,6 @@
f90819
     }
f90819
 
f90819
 
f90819
-
f90819
     /**
f90819
      *  Decide which way to render. HTML or XML.
f90819
      */
f90819
@@ -1259,13 +1274,15 @@
f90819
         throws IOException, ServletException {
f90819
 
f90819
         Source xsltSource = findXsltInputStream(cacheEntry.context);
f90819
-        if (xsltSource ==null) {
f90819
+
f90819
+        if (xsltSource == null) {
f90819
             return renderHtml(contextPath, cacheEntry);
f90819
         }
f90819
         return renderXml(contextPath, cacheEntry, xsltSource);
f90819
 
f90819
     }
f90819
 
f90819
+    
f90819
     /**
f90819
      * Return an InputStream to an HTML representation of the contents
f90819
      * of this directory.
f90819
@@ -1362,11 +1379,27 @@
f90819
             sb.append("]]></readme>");
f90819
         }
f90819
 
f90819
-
f90819
         sb.append("</listing>");
f90819
 
f90819
-
f90819
+        // Prevent possible memory leak. Ensure Transformer and
f90819
+        // TransformerFactory are not loaded from the web application.
f90819
+        ClassLoader original;
f90819
+        if (Globals.IS_SECURITY_ENABLED) {
f90819
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
f90819
+            original = AccessController.doPrivileged(pa);
f90819
+        } else {
f90819
+            original = Thread.currentThread().getContextClassLoader();
f90819
+        }
f90819
         try {
f90819
+            if (Globals.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa =
f90819
+                        new PrivilegedSetTccl(DefaultServlet.class.getClassLoader());
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(
f90819
+                        DefaultServlet.class.getClassLoader());
f90819
+            }
f90819
+
f90819
             TransformerFactory tFactory = TransformerFactory.newInstance();
f90819
             Source xmlSource = new StreamSource(new StringReader(sb.toString()));
f90819
             Transformer transformer = tFactory.newTransformer(xsltSource);
f90819
@@ -1379,6 +1412,13 @@
f90819
             return (new ByteArrayInputStream(stream.toByteArray()));
f90819
         } catch (TransformerException e) {
f90819
             throw new ServletException("XSL transformer error", e);
f90819
+        } finally {
f90819
+            if (Globals.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(original);
f90819
+            }
f90819
         }
f90819
     }
f90819
 
f90819
@@ -1530,7 +1570,9 @@
f90819
             sb.append("
");
f90819
         }
f90819
 
f90819
-        sb.append("

").append(ServerInfo.getServerInfo()).append("

");
f90819
+        if (showServerInfo) {
f90819
+            sb.append("

").append(ServerInfo.getServerInfo()).append("

");
f90819
+        }
f90819
         sb.append("</body>\r\n");
f90819
         sb.append("</html>\r\n");
f90819
 
f90819
@@ -1588,7 +1630,7 @@
f90819
 
f90819
 
f90819
     /**
f90819
-     * Return the xsl template inputstream (if possible)
f90819
+     * Return a Source for the xsl template (if possible)
f90819
      */
f90819
     protected Source findXsltInputStream(DirContext directory)
f90819
         throws IOException {
f90819
@@ -1630,31 +1672,32 @@
f90819
         /*  Open and read in file in one fell swoop to reduce chance
f90819
          *  chance of leaving handle open.
f90819
          */
f90819
-       if (globalXsltFile != null) {
f90819
-          File f = validateGlobalXsltFile();
f90819
-          if (f != null ){
f90819
-              FileInputStream fis = null;
f90819
-              try {
f90819
-                 fis = new FileInputStream(f);
f90819
-                 byte b[] = new byte[(int)f.length()]; /* danger! */
f90819
-                 fis.read(b);
f90819
-                 return new StreamSource(new ByteArrayInputStream(b));
f90819
-              } finally {
f90819
-                  if (fis != null) {
f90819
-                      try {
f90819
-                          fis.close();
f90819
-                      } catch(IOException ioe) {
f90819
-                          // ignore
f90819
-                      }
f90819
-                  }
f90819
-              }
f90819
-           }
f90819
+        if (globalXsltFile != null) {
f90819
+            File f = validateGlobalXsltFile();
f90819
+            if (f != null){
f90819
+                FileInputStream fis = null;
f90819
+                try {
f90819
+                    fis = new FileInputStream(f);
f90819
+                    byte b[] = new byte[(int)f.length()]; /* danger! */
f90819
+                    fis.read(b);
f90819
+                    return new StreamSource(new ByteArrayInputStream(b));
f90819
+                } finally {
f90819
+                    if (fis != null) {
f90819
+                        try {
f90819
+                            fis.close();
f90819
+                        } catch (IOException ioe) {
f90819
+                            // Ignore
f90819
+                        }
f90819
+                    }
f90819
+                }
f90819
+            }
f90819
         }
f90819
 
f90819
         return null;
f90819
 
f90819
     }
f90819
 
f90819
+
f90819
     private File validateGlobalXsltFile() {
f90819
         
f90819
         File result = null;
f90819
@@ -1705,6 +1748,7 @@
f90819
         return candidate;
f90819
     }
f90819
 
f90819
+
f90819
     private Source secureXslt(InputStream is) {
f90819
         // Need to filter out any external entities
f90819
         Source result = null;
f90819
@@ -1740,7 +1784,6 @@
f90819
 
f90819
     // -------------------------------------------------------- protected Methods
f90819
 
f90819
-
f90819
     /**
f90819
      * Check if sendfile can be used.
f90819
      */
f90819
@@ -2240,9 +2283,6 @@
f90819
     }
f90819
 
f90819
 
f90819
-    // ------------------------------------------------------ Range Inner Class
f90819
-
f90819
-
f90819
     protected static class Range {
f90819
 
f90819
         public long start;
f90819
@@ -2259,6 +2299,7 @@
f90819
         }
f90819
     }
f90819
 
f90819
+
f90819
     /**
f90819
      * This is secure in the sense that any attempt to use an external entity
f90819
      * will trigger an exception.
f90819
@@ -2288,4 +2329,3 @@
f90819
         }
f90819
     }
f90819
 }
f90819
-
f90819
--- webapps/docs/changelog.xml.orig	2014-07-24 18:29:38.917021000 -0400
f90819
+++ webapps/docs/changelog.xml	2014-07-24 18:36:52.526481000 -0400
f90819
@@ -158,6 +158,15 @@
f90819
         <bug>55176</bug>: Correctly handle regular expressions within SSI
f90819
         expressions that contain an equals character. (markt)
f90819
       </fix>
f90819
+      <fix>
f90819
+        Ensure that a TLD parser obtained from the cache has the correct value
f90819
+        of blockExternal. (markt)
f90819
+      </fix>
f90819
+      <add>
f90819
+        Extend XML factory, parser etc. memory leak protection to cover some
f90819
+        additional locations where, theoretically, a memory leak could occur.
f90819
+        (markt)
f90819
+      </add>
f90819
     </changelog>
f90819
   </subsection>
f90819
   <subsection name="Coyote">
f90819
@@ -352,6 +361,10 @@
f90819
         request if the CRLF terminating the request line was split across
f90819
         multiple packets. Patch by Konstantin Preißer. (markt)
f90819
       </fix>
f90819
+      <fix>
f90819
+        Only create XML parsing objects if required and fix associated potential
f90819
+        memory leak in the default Servlet. (markt)
f90819
+      </fix>
f90819
     </changelog>
f90819
   </subsection>
f90819
   <subsection name="Jasper">
f90819
--- java/org/apache/jasper/xmlparser/ParserUtils.java.orig	2014-07-24 18:29:38.952016000 -0400
f90819
+++ java/org/apache/jasper/xmlparser/ParserUtils.java	2014-07-24 18:31:18.746354000 -0400
f90819
@@ -18,6 +18,7 @@
f90819
 
f90819
 import java.io.IOException;
f90819
 import java.io.InputStream;
f90819
+import java.security.AccessController;
f90819
 
f90819
 import javax.xml.parsers.DocumentBuilder;
f90819
 import javax.xml.parsers.DocumentBuilderFactory;
f90819
@@ -29,6 +30,8 @@
f90819
 import org.apache.tomcat.util.descriptor.DigesterFactory;
f90819
 import org.apache.tomcat.util.descriptor.LocalResolver;
f90819
 import org.apache.tomcat.util.descriptor.XmlErrorHandler;
f90819
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
f90819
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
f90819
 import org.w3c.dom.Comment;
f90819
 import org.w3c.dom.Document;
f90819
 import org.w3c.dom.NamedNodeMap;
f90819
@@ -36,7 +39,6 @@
f90819
 import org.w3c.dom.NodeList;
f90819
 import org.w3c.dom.Text;
f90819
 import org.xml.sax.EntityResolver;
f90819
-import org.xml.sax.ErrorHandler;
f90819
 import org.xml.sax.InputSource;
f90819
 import org.xml.sax.SAXException;
f90819
 import org.xml.sax.SAXParseException;
f90819
@@ -48,16 +50,10 @@
f90819
  * use a separate class loader for the parser to be used.
f90819
  *
f90819
  * @author Craig R. McClanahan
f90819
- * @version $Id: ParserUtils.java 1549529 2013-12-09 10:05:56Z markt $
f90819
  */
f90819
 public class ParserUtils {
f90819
 
f90819
     /**
f90819
-     * An error handler for use when parsing XML documents.
f90819
-     */
f90819
-    static ErrorHandler errorHandler = new XmlErrorHandler();
f90819
-
f90819
-    /**
f90819
      * An entity resolver for use when parsing XML documents.
f90819
      */
f90819
     static EntityResolver entityResolver;
f90819
@@ -99,15 +95,46 @@
f90819
         Document document = null;
f90819
 
f90819
         // Perform an XML parse of this document, via JAXP
f90819
+        ClassLoader original;
f90819
+        if (Constants.IS_SECURITY_ENABLED) {
f90819
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
f90819
+            original = AccessController.doPrivileged(pa);
f90819
+        } else {
f90819
+            original = Thread.currentThread().getContextClassLoader();
f90819
+        }
f90819
         try {
f90819
+            if (Constants.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa =
f90819
+                        new PrivilegedSetTccl(ParserUtils.class.getClassLoader());
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(
f90819
+                        ParserUtils.class.getClassLoader());
f90819
+            }
f90819
+            
f90819
             DocumentBuilderFactory factory =
f90819
                 DocumentBuilderFactory.newInstance();
f90819
             factory.setNamespaceAware(true);
f90819
             factory.setValidating(validating);
f90819
+            if (validating) {
f90819
+                // Enable DTD validation
f90819
+                factory.setFeature(
f90819
+                        "http://xml.org/sax/features/validation",
f90819
+                        true);
f90819
+                // Enable schema validation
f90819
+                factory.setFeature(
f90819
+                        "http://apache.org/xml/features/validation/schema",
f90819
+                        true);
f90819
+            }
f90819
             DocumentBuilder builder = factory.newDocumentBuilder();
f90819
             builder.setEntityResolver(entityResolverInstance);
f90819
-            builder.setErrorHandler(errorHandler);
f90819
+            XmlErrorHandler handler = new XmlErrorHandler();
f90819
+            builder.setErrorHandler(handler);
f90819
             document = builder.parse(is);
f90819
+            if (!handler.getErrors().isEmpty()) {
f90819
+                // throw the first to indicate there was a error during processing
f90819
+                throw handler.getErrors().iterator().next();
f90819
+            }
f90819
         } catch (ParserConfigurationException ex) {
f90819
             throw new JasperException
f90819
                 (Localizer.getMessage("jsp.error.parse.xml", location), ex);
f90819
@@ -124,6 +151,13 @@
f90819
         } catch (IOException io) {
f90819
             throw new JasperException
f90819
                 (Localizer.getMessage("jsp.error.parse.xml", location), io);
f90819
+        } finally {
f90819
+            if (Constants.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(original);
f90819
+            }
f90819
         }
f90819
 
f90819
         // Convert the resulting document to a graph of TreeNodes
f90819
--- java/org/apache/jasper/compiler/JspDocumentParser.java.orig	2014-07-24 18:29:38.974016000 -0400
f90819
+++ java/org/apache/jasper/compiler/JspDocumentParser.java	2014-07-24 18:31:18.774352000 -0400
f90819
@@ -20,6 +20,7 @@
f90819
 import java.io.FileNotFoundException;
f90819
 import java.io.IOException;
f90819
 import java.io.InputStream;
f90819
+import java.security.AccessController;
f90819
 import java.util.Iterator;
f90819
 import java.util.List;
f90819
 import java.util.jar.JarFile;
f90819
@@ -35,6 +36,8 @@
f90819
 import org.apache.jasper.JspCompilationContext;
f90819
 import org.apache.tomcat.util.descriptor.DigesterFactory;
f90819
 import org.apache.tomcat.util.descriptor.LocalResolver;
f90819
+import org.apache.tomcat.util.security.PrivilegedGetTccl;
f90819
+import org.apache.tomcat.util.security.PrivilegedSetTccl;
f90819
 import org.xml.sax.Attributes;
f90819
 import org.xml.sax.InputSource;
f90819
 import org.xml.sax.Locator;
f90819
@@ -129,7 +132,7 @@
f90819
                 Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
f90819
         boolean blockExternal;
f90819
         if (blockExternalString == null) {
f90819
-            blockExternal = Constants.IS_SECURITY_ENABLED;
f90819
+            blockExternal = true;
f90819
         } else {
f90819
             blockExternal = Boolean.parseBoolean(blockExternalString);
f90819
         }
f90819
@@ -1464,33 +1467,58 @@
f90819
         JspDocumentParser jspDocParser)
f90819
         throws Exception {
f90819
 
f90819
-        SAXParserFactory factory = SAXParserFactory.newInstance();
f90819
-
f90819
-        factory.setNamespaceAware(true);
f90819
-        // Preserve xmlns attributes
f90819
-        factory.setFeature(
f90819
-            "http://xml.org/sax/features/namespace-prefixes",
f90819
-            true);
f90819
-
f90819
-        factory.setValidating(validating);
f90819
-        if (validating) {
f90819
-            // Enable DTD validation
f90819
-            factory.setFeature(
f90819
-                    "http://xml.org/sax/features/validation",
f90819
-                    true);
f90819
-            // Enable schema validation
f90819
-            factory.setFeature(
f90819
-                    "http://apache.org/xml/features/validation/schema",
f90819
-                    true);
f90819
+        ClassLoader original;
f90819
+        if (Constants.IS_SECURITY_ENABLED) {
f90819
+            PrivilegedGetTccl pa = new PrivilegedGetTccl();
f90819
+            original = AccessController.doPrivileged(pa);
f90819
+        } else {
f90819
+            original = Thread.currentThread().getContextClassLoader();
f90819
         }
f90819
+        try {
f90819
+            if (Constants.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa =
f90819
+                        new PrivilegedSetTccl(JspDocumentParser.class.getClassLoader());
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(
f90819
+                        JspDocumentParser.class.getClassLoader());
f90819
+            }
f90819
+
f90819
+            SAXParserFactory factory = SAXParserFactory.newInstance();
f90819
 
f90819
-        // Configure the parser
f90819
-        SAXParser saxParser = factory.newSAXParser();
f90819
-        XMLReader xmlReader = saxParser.getXMLReader();
f90819
-        xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
f90819
-        xmlReader.setErrorHandler(jspDocParser);
f90819
+            factory.setNamespaceAware(true);
f90819
+            // Preserve xmlns attributes
f90819
+            factory.setFeature(
f90819
+                "http://xml.org/sax/features/namespace-prefixes",
f90819
+                true);
f90819
 
f90819
-        return saxParser;
f90819
+            factory.setValidating(validating);
f90819
+            if (validating) {
f90819
+                // Enable DTD validation
f90819
+                factory.setFeature(
f90819
+                        "http://xml.org/sax/features/validation",
f90819
+                        true);
f90819
+                // Enable schema validation
f90819
+                factory.setFeature(
f90819
+                        "http://apache.org/xml/features/validation/schema",
f90819
+                        true);
f90819
+            }
f90819
+
f90819
+            // Configure the parser
f90819
+            SAXParser saxParser = factory.newSAXParser();
f90819
+            XMLReader xmlReader = saxParser.getXMLReader();
f90819
+            xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
f90819
+            xmlReader.setErrorHandler(jspDocParser);
f90819
+
f90819
+            return saxParser;
f90819
+        } finally {
f90819
+            if (Constants.IS_SECURITY_ENABLED) {
f90819
+                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
f90819
+                AccessController.doPrivileged(pa);
f90819
+            } else {
f90819
+                Thread.currentThread().setContextClassLoader(original);
f90819
+            }
f90819
+        }
f90819
     }
f90819
 
f90819
     /*
f90819
--- java/org/apache/tomcat/util/security/PrivilegedGetTccl.java.orig	2014-07-24 18:59:42.923103000 -0400
f90819
+++ java/org/apache/tomcat/util/security/PrivilegedGetTccl.java	2014-07-24 18:56:17.729411000 -0400
f90819
@@ -0,0 +1,28 @@
f90819
+/*
f90819
+ * Licensed to the Apache Software Foundation (ASF) under one or more
f90819
+ * contributor license agreements.  See the NOTICE file distributed with
f90819
+ * this work for additional information regarding copyright ownership.
f90819
+ * The ASF licenses this file to You under the Apache License, Version 2.0
f90819
+ * (the "License"); you may not use this file except in compliance with
f90819
+ * the License.  You may obtain a copy of the License at
f90819
+ *
f90819
+ *      http://www.apache.org/licenses/LICENSE-2.0
f90819
+ *
f90819
+ * Unless required by applicable law or agreed to in writing, software
f90819
+ * distributed under the License is distributed on an "AS IS" BASIS,
f90819
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
f90819
+ * See the License for the specific language governing permissions and
f90819
+ * limitations under the License.
f90819
+ */
f90819
+package org.apache.tomcat.util.security;
f90819
+
f90819
+import java.security.PrivilegedAction;
f90819
+
f90819
+public class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {
f90819
+    @Override
f90819
+    public ClassLoader run() {
f90819
+        return Thread.currentThread().getContextClassLoader();
f90819
+    }
f90819
+}
f90819
+
f90819
+
f90819
--- java/org/apache/tomcat/util/security/PrivilegedSetTccl.java.orig	2014-07-24 18:59:42.928107000 -0400
f90819
+++ java/org/apache/tomcat/util/security/PrivilegedSetTccl.java	2014-07-24 18:56:17.736421000 -0400
f90819
@@ -0,0 +1,34 @@
f90819
+/*
f90819
+ * Licensed to the Apache Software Foundation (ASF) under one or more
f90819
+ * contributor license agreements.  See the NOTICE file distributed with
f90819
+ * this work for additional information regarding copyright ownership.
f90819
+ * The ASF licenses this file to You under the Apache License, Version 2.0
f90819
+ * (the "License"); you may not use this file except in compliance with
f90819
+ * the License.  You may obtain a copy of the License at
f90819
+ *
f90819
+ *      http://www.apache.org/licenses/LICENSE-2.0
f90819
+ *
f90819
+ * Unless required by applicable law or agreed to in writing, software
f90819
+ * distributed under the License is distributed on an "AS IS" BASIS,
f90819
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
f90819
+ * See the License for the specific language governing permissions and
f90819
+ * limitations under the License.
f90819
+ */
f90819
+package org.apache.tomcat.util.security;
f90819
+
f90819
+import java.security.PrivilegedAction;
f90819
+
f90819
+public class PrivilegedSetTccl implements PrivilegedAction<Void> {
f90819
+
f90819
+    private ClassLoader cl;
f90819
+
f90819
+    public PrivilegedSetTccl(ClassLoader cl) {
f90819
+        this.cl = cl;
f90819
+    }
f90819
+
f90819
+    @Override
f90819
+    public Void run() {
f90819
+        Thread.currentThread().setContextClassLoader(cl);
f90819
+        return null;
f90819
+    }
f90819
+}
f90819
\ No newline at end of file