You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by ro...@apache.org on 2010/07/06 21:52:50 UTC

svn commit: r960998 - in /incubator/wink/trunk/wink-common/src/main: java/org/apache/wink/common/internal/providers/entity/SourceProvider.java resources/org/apache/wink/common/internal/i18n/resource.properties

Author: rott
Date: Tue Jul  6 19:52:49 2010
New Revision: 960998

URL: http://svn.apache.org/viewvc?rev=960998&view=rev
Log:
WINK-298 followup: fix hudson build break, handle Sun JDK5 NPE bug in DocumentBuilder.parse when DTD is present

Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/SourceProvider.java
    incubator/wink/trunk/wink-common/src/main/resources/org/apache/wink/common/internal/i18n/resource.properties

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/SourceProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/SourceProvider.java?rev=960998&r1=960997&r2=960998&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/SourceProvider.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/SourceProvider.java Tue Jul  6 19:52:49 2010
@@ -137,20 +137,18 @@ public abstract class SourceProvider imp
             return (DOMSource.class == type && super.isReadable(mediaType));
         }
         
-        private void setupDocumentBuilderToFilterDTD(DocumentBuilder dbuilder) {
-            /*
-             * You might think you could just do this to prevent entity expansion:
-             *    documentBuilderFactory.setExpandEntityReferences(false);
-             * In fact, you should not do that, because it will just increase the size
-             * of your DOMSource.  We want to actively reject XML when a DTD is present, so...
-             */
-            dbuilder.setEntityResolver(new EntityResolver() {
-                public InputSource resolveEntity(String name, String baseURI)
-                throws SAXException, IOException {
-                    // we don't support entity resolution here
-                    throw new SAXParseException(Messages.getMessage("entityRefsNotSupported"), null);  //$NON-NLS-1$
+        private DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
+            RuntimeContext runtimeContext = RuntimeContextTLS.getRuntimeContext();
+            WinkConfiguration winkConfig = runtimeContext.getAttribute(WinkConfiguration.class);
+            if (winkConfig != null) {
+                Properties props = winkConfig.getProperties();
+                if (props != null) {
+                    // use valueOf method to require the word "true"
+                    if (Boolean.valueOf(props.getProperty("wink.supportDTDEntityExpansion"))) { //$NON-NLS-1$
+                        return documentBuilderFactory.newDocumentBuilder();
+                    }
                 }
-            });
+            }
             try {
                 // important: keep this order
                 documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
@@ -160,10 +158,26 @@ public abstract class SourceProvider imp
             }
             try {
                 // workaround for JDK5 bug that causes NPE in checking done due to above FEATURE_SECURE_PROCESSING
-                documentBuilderFactory.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false); //$NON-NLS-1$
+                // For Apache Xerces-J:  https://issues.apache.org/jira/browse/XERCESJ-977
+                documentBuilderFactory.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", Boolean.FALSE); //$NON-NLS-1$
             } catch (ParserConfigurationException e) {
                 // possible if not on apache parser?  ignore...
             }
+            DocumentBuilder dbuilder = documentBuilderFactory.newDocumentBuilder();
+            /*
+             * You might think you could just do this to prevent entity expansion:
+             *    documentBuilderFactory.setExpandEntityReferences(false);
+             * In fact, you should not do that, because it will just increase the size
+             * of your DOMSource.  We want to actively reject XML when a DTD is present, so...
+             */
+            dbuilder.setEntityResolver(new EntityResolver() {
+                public InputSource resolveEntity(String name, String baseURI)
+                throws SAXException, IOException {
+                    // we don't support entity resolution here
+                    throw new SAXParseException(Messages.getMessage("entityRefsNotSupported"), null);  //$NON-NLS-1$
+                }
+            });
+            return dbuilder;
         }
 
         public DOMSource readFrom(Class<DOMSource> type,
@@ -174,19 +188,25 @@ public abstract class SourceProvider imp
                                   InputStream entityStream) throws IOException,
             WebApplicationException {
             try {
-                DocumentBuilder dbuilder = documentBuilderFactory.newDocumentBuilder();
-                RuntimeContext runtimeContext = RuntimeContextTLS.getRuntimeContext();
-                WinkConfiguration winkConfig = runtimeContext.getAttribute(WinkConfiguration.class);
-                if (winkConfig != null) {
-                    Properties props = winkConfig.getProperties();
-                    if (props != null) {
-                        // use valueOf method to require the word "true"
-                        if (!Boolean.valueOf(props.getProperty("wink.supportDTDEntityExpansion"))) { //$NON-NLS-1$
-                            setupDocumentBuilderToFilterDTD(dbuilder);
-                        }
+                DocumentBuilder dbuilder = getDocumentBuilder();  //documentBuilderFactory.newDocumentBuilder();
+                return new DOMSource(dbuilder.parse(entityStream));
+            } catch (NullPointerException npe) {
+                // For Sun JDK5, they will never fix this problem.  See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6181020
+                // Let's be as safe as possible, and check that all the conditions that indicate we're avoiding DTD expansion attack
+                // are present.  We'll need the catch the NPE when we do the parse, inspect the stack, and fail gracefully.  Ugly
+                // hack, but it works.  (Ideally, we'd also inspect the entityStream to ensure we're definitely doing DTD expansion
+                // when we get this NPE, but we cannot reliably reset the stream and re-read it due to possibly getting a stream
+                // that does not support .reset().)
+                StackTraceElement[] stackTraceElement = npe.getStackTrace();
+                for(int i = 0; i < stackTraceElement.length; i++) {
+                    if(stackTraceElement[i].getClassName().equals("com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl") //$NON-NLS-1$
+                            && (stackTraceElement[i].getMethodName().equals("setChunkIndex"))) { //$NON-NLS-1$
+                        // then it's really Sun JDK5, and as far as we can tell, it's related to DTD expansion attack, and we should fail gracefully
+                        logger.error(Messages.getMessage("entityRefsNotSupportedSunJDK5"), npe); //$NON-NLS-1$
+                        throw new WebApplicationException(Response.Status.BAD_REQUEST);
                     }
                 }
-                return new DOMSource(dbuilder.parse(entityStream));
+                throw npe;
             } catch (SAXException e) {
                 logger.error(Messages.getMessage("saxParseException", type.getName()), e); //$NON-NLS-1$
                 throw new WebApplicationException(e, Response.Status.BAD_REQUEST);

Modified: incubator/wink/trunk/wink-common/src/main/resources/org/apache/wink/common/internal/i18n/resource.properties
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/resources/org/apache/wink/common/internal/i18n/resource.properties?rev=960998&r1=960997&r2=960998&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/resources/org/apache/wink/common/internal/i18n/resource.properties (original)
+++ incubator/wink/trunk/wink-common/src/main/resources/org/apache/wink/common/internal/i18n/resource.properties Tue Jul  6 19:52:49 2010
@@ -209,6 +209,7 @@ providerShouldBeAnnotatedDirectly=The @j
 rootResourceShouldBeAnnotatedDirectly=The @javax.ws.rs.Path annotation was found on a superclass or interface on the {0} class.  Annotate @javax.ws.rs.Path on the root resource class directly to ensure portability between environments.
 providerIsInterfaceOrAbstract=A @javax.ws.rs.ext.Provider annotation was found on {0} which is an interface or an abstract class and is being ignored. Annotate @javax.ws.rs.ext.Provider on the provider implementation or base class directly and return that in your javax.ws.rs.core.Application subclass.
 entityRefsNotSupported=Entity references are not supported in XML documents due to possible security vulnerabilities.
+entityRefsNotSupportedSunJDK5=Entity references are not supported in XML documents due to possible security vulnerabilities.  Sun JDK5 does not support the necessary feature to prevent a NullPointerException.  See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6181020
 saxParseException=The system cannot parse the XML content into a {0} instance.  Verify that the XML content is valid.
 saxParserConfigurationException=The system cannot configure the SAX parser with the given configuration parameter.
 badXMLReaderInitialStart=The XMLStreamReader instance has already been partially processed.