Mark Wielaard wrote:
Hi Olivier,
On Mon, 2006-03-20 at 20:27 +0100, Olivier Jolly wrote:
here is attached another version of the patch rewrote with
StringTokenizer and an iterative algorithm. It still passes all the
mauve test about resources and looks more efficient.
Yes. Thanks please do check this in with the original ChangeLog entry.
Some nitpicks below.
[...]
Ok, I checked in the adapted code by fixing (hopefully) the indentation
and changing the semantic of the helper procedure to return a canonical
file or null and checking the existence there to simplify the calling
code, as you suggested.
The updated changelog entry is then
2006-03-25 Olivier Jolly <[EMAIL PROTECTED]>
* java/net/URLClassLoader.java (FileURLLoader.getResource): Added test
to validate all components of a resource path.
(FileURLLoader.walkPathComponents): Helper which ensures that we are
allowed to walk through every component of a resouce path.
Thanks for the feedback,
cheers
+Olivier
Index: URLClassLoader.java
===================================================================
RCS file: /sources/classpath/classpath/java/net/URLClassLoader.java,v
retrieving revision 1.45
diff -u -r1.45 URLClassLoader.java
--- URLClassLoader.java 5 Mar 2006 17:20:51 -0000 1.45
+++ URLClassLoader.java 25 Mar 2006 20:22:23 -0000
@@ -538,9 +538,14 @@
{
try
{
- File file = new File(dir, name).getCanonicalFile();
- if (file.exists())
- return new FileResource(this, file);
+ // Make sure that all components in name are valid by walking through
+ // them
+ File file = walkPathComponents(name);
+
+ if (file == null)
+ return null;
+
+ return new FileResource(this, file);
}
catch (IOException e)
{
@@ -548,6 +553,65 @@
}
return null;
}
+
+ /**
+ * Walk all path tokens and check them for validity. At no moment, we are
+ * allowed to reach a directory located "above" the root directory, stored
+ * in "dir" property. We are also not allowed to enter a non existing
+ * directory or a non directory component (plain file, symbolic link, ...).
+ * An empty or null path is valid. Pathnames components are separated by
+ * <code>File.separatorChar</code>
+ *
+ * @param resourceFileName the name to be checked for validity.
+ * @return the canonical file pointed by the resourceFileName or null if the
+ * walking failed
+ * @throws IOException in case of issue when creating the canonical
+ * resulting file
+ * @see File#separatorChar
+ */
+ private File walkPathComponents(String resourceFileName) throws IOException
+ {
+ StringTokenizer stringTokenizer = new StringTokenizer(resourceFileName, File.separator);
+ File currentFile = dir;
+ int tokenCount = stringTokenizer.countTokens();
+
+ for (int i = 0; i < tokenCount - 1; i++)
+ {
+ String currentToken = stringTokenizer.nextToken();
+
+ // If we are at the root directory and trying to go up, the walking is
+ // finished with an error
+ if ("..".equals(currentToken) && currentFile.equals(dir))
+ return null;
+
+ currentFile = new File(currentFile, currentToken);
+
+ // If the current file doesn't exist or is not a directory, the walking is
+ // finished with an error
+ if (! (currentFile.exists() && currentFile.isDirectory()))
+ return null;
+
+ }
+
+ // Treat the last token differently, if it exists, because it does not need
+ // to be a directory
+ if (tokenCount > 0)
+ {
+ String currentToken = stringTokenizer.nextToken();
+
+ if ("..".equals(currentToken) && currentFile.equals(dir))
+ return null;
+
+ currentFile = new File(currentFile, currentToken);
+
+ // If the current file doesn't exist, the walking is
+ // finished with an error
+ if (! currentFile.exists())
+ return null;
+ }
+
+ return currentFile.getCanonicalFile();
+ }
}
static final class FileResource extends Resource