From: markt Date: Fri, 23 Jul 2010 14:30:26 +0000 (+0000) Subject: Handle the edge cases where resources packaged in JARs have names that start with... X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=adf02790487328e189336d578f854b21be1ef386;p=tomcat7.0 Handle the edge cases where resources packaged in JARs have names that start with a single quote character or a double quote character. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@967107 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/naming/resources/WARDirContext.java b/java/org/apache/naming/resources/WARDirContext.java index 850fa1c3b..37791794d 100644 --- a/java/org/apache/naming/resources/WARDirContext.java +++ b/java/org/apache/naming/resources/WARDirContext.java @@ -198,7 +198,7 @@ public class WARDirContext extends BaseDirContext { Name name; try { - name = new CompositeName(strName); + name = getEscapedJndiName(strName); } catch (InvalidNameException e) { log.info(sm.getString("resources.invalidName", strName), e); return null; @@ -219,6 +219,19 @@ public class WARDirContext extends BaseDirContext { /** + * JNDI treats ' and " as reserved characters therefore they need to be + * escaped as part of converting file names to JNDI names. Note that while + * ' can be used in Windows and Unix file names, " is only valid on Unix. + * This method assumes that the string is currently unquoted. + * + * @return A valid JNDI name + * @throws InvalidNameException + */ + private Name getEscapedJndiName(String name) throws InvalidNameException { + return new CompositeName(name.replace("'", "\\'").replace("\"", "")); + } + + /** * Unbinds the named object. Removes the terminal atomic name in name * from the target context--that named by all but the terminal atomic * part of name. @@ -273,7 +286,7 @@ public class WARDirContext extends BaseDirContext { @Override public NamingEnumeration list(String name) throws NamingException { - return list(new CompositeName(name)); + return list(getEscapedJndiName(name)); } @@ -320,7 +333,7 @@ public class WARDirContext extends BaseDirContext { protected NamingEnumeration doListBindings(String strName) throws NamingException { - Name name = new CompositeName(strName); + Name name = getEscapedJndiName(strName); if (name.isEmpty()) return new NamingContextBindingsEnumeration(list(entries).iterator(), @@ -426,7 +439,7 @@ public class WARDirContext extends BaseDirContext { @Override protected Attributes doGetAttributes(String name, String[] attrIds) throws NamingException { - return getAttributes(new CompositeName(name), attrIds); + return getAttributes(getEscapedJndiName(name), attrIds); } @@ -760,8 +773,8 @@ public class WARDirContext extends BaseDirContext { int currentPos = -1; int lastPos = 0; while ((currentPos = name.indexOf('/', lastPos)) != -1) { - Name parentName = new CompositeName(name.substring(0, lastPos)); - Name childName = new CompositeName(name.substring(0, currentPos)); + Name parentName = getEscapedJndiName(name.substring(0, lastPos)); + Name childName = getEscapedJndiName(name.substring(0, currentPos)); String entryName = name.substring(lastPos, currentPos); // Parent should have been created in last cycle through // this loop @@ -781,7 +794,7 @@ public class WARDirContext extends BaseDirContext { lastPos = currentPos + 1; } String entryName = name.substring(pos + 1, name.length()); - Name compositeName = new CompositeName(name.substring(0, pos)); + Name compositeName = getEscapedJndiName(name.substring(0, pos)); Entry parent = treeLookup(compositeName); Entry child = new Entry(entryName, entry); if (parent != null) diff --git a/test/org/apache/naming/resources/TestWarDirContext.java b/test/org/apache/naming/resources/TestWarDirContext.java new file mode 100644 index 000000000..a21a501c8 --- /dev/null +++ b/test/org/apache/naming/resources/TestWarDirContext.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.naming.resources; + +import java.io.File; + +import org.apache.catalina.core.JreMemoryLeakPreventionListener; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.tomcat.util.buf.ByteChunk; + +public class TestWarDirContext extends TomcatBaseTest { + + @Override + public void setUp() throws Exception { + super.setUp(); + + Tomcat tomcat = getTomcatInstance(); + + // The test fails if JreMemoryLeakPreventionListener is not + // present. The listener affects the JVM, and thus not only the current, + // but also the subsequent tests that are run in the same JVM. So it is + // fair to add it in every test. + tomcat.getServer().addLifecycleListener( + new JreMemoryLeakPreventionListener()); + } + + /** + * Check https://jira.springsource.org/browse/SPR-7350 isn't really an issue + */ + public void testLookupException() throws Exception { + Tomcat tomcat = getTomcatInstance(); + + File appDir = new File("test/webapp-3.0-fragments"); + // app dir is relative to server home + tomcat.addWebapp(null, "/test", appDir.getAbsolutePath()); + + tomcat.start(); + + ByteChunk bc = getUrl("http://localhost:" + getPort() + + "/test/warDirContext.jsp"); + assertEquals("

java.lang.ClassNotFoundException

", + bc.toString()); + } + + + /** + * Additional test following on from SPR-7350 above to check files that + * contain JNDI reserved characters can be served when caching is enabled. + */ + public void testReservedJNDIFileNamesWithCache() throws Exception { + Tomcat tomcat = getTomcatInstance(); + + File appDir = new File("test/webapp-3.0-fragments"); + // app dir is relative to server home + StandardContext ctxt = (StandardContext) tomcat.addWebapp( + null, "/test", appDir.getAbsolutePath()); + ctxt.setCachingAllowed(true); + + tomcat.start(); + + // Should be found in resources.jar + ByteChunk bc = getUrl("http://localhost:" + getPort() + + "/test/'singlequote.jsp"); + assertEquals("

'singlequote.jsp in resources.jar

", + bc.toString()); + + // Should be found in file system + bc = getUrl("http://localhost:" + getPort() + + "/test/'singlequote2.jsp"); + assertEquals("

'singlequote2.jsp in file system

", + bc.toString()); + } + + + /** + * Additional test following on from SPR-7350 above to check files that + * contain JNDI reserved characters can be served when caching is disabled. + */ + public void testReservedJNDIFileNamesNoCache() throws Exception { + Tomcat tomcat = getTomcatInstance(); + + File appDir = new File("test/webapp-3.0-fragments"); + // app dir is relative to server home + StandardContext ctxt = (StandardContext) tomcat.addWebapp( + null, "/test", appDir.getAbsolutePath()); + ctxt.setCachingAllowed(false); + + tomcat.start(); + + // Should be found in resources.jar + ByteChunk bc = getUrl("http://localhost:" + getPort() + + "/test/'singlequote.jsp"); + assertEquals("

'singlequote.jsp in resources.jar

", + bc.toString()); + + // Should be found in file system + bc = getUrl("http://localhost:" + getPort() + + "/test/'singlequote2.jsp"); + assertEquals("

'singlequote2.jsp in file system

", + bc.toString()); + } +} diff --git a/test/webapp-3.0-fragments/'singlequote2.jsp b/test/webapp-3.0-fragments/'singlequote2.jsp new file mode 100644 index 000000000..dce8317c2 --- /dev/null +++ b/test/webapp-3.0-fragments/'singlequote2.jsp @@ -0,0 +1,19 @@ +<%-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--%><%-- + Resource file that is present both in the web application and in the + WEB-INF/lib/resources.jar file. The one in the web application should win. +--%>

'singlequote2.jsp in file system

\ No newline at end of file diff --git a/test/webapp-3.0-fragments/WEB-INF/lib/resources.jar b/test/webapp-3.0-fragments/WEB-INF/lib/resources.jar index a847e05a8..e8524e6e5 100644 Binary files a/test/webapp-3.0-fragments/WEB-INF/lib/resources.jar and b/test/webapp-3.0-fragments/WEB-INF/lib/resources.jar differ diff --git a/test/webapp-3.0-fragments/warDirContext.jsp b/test/webapp-3.0-fragments/warDirContext.jsp new file mode 100644 index 000000000..09bbb1640 --- /dev/null +++ b/test/webapp-3.0-fragments/warDirContext.jsp @@ -0,0 +1,21 @@ +<%-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--%><% +try { + Class clazz = Class.forName("'P'"); +} catch (Exception e) { + out.print("

" + e.getClass().getName() + "

"); +}%> \ No newline at end of file diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 13f58c0f2..212851c4b 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -189,6 +189,10 @@ that make multiple class to Request.getAttributeNames(). Patch provided by Sampo Savolainen. (markt) + + Handle the edge cases where resources packaged in JARs have names that + start with a single quote character or a double quote character. (markt) +