From 7f0fbff17edcfd60832ac19b7aa6c115b8b052aa Mon Sep 17 00:00:00 2001 From: thesnowgoose Date: Tue, 29 Mar 2016 12:49:56 -0700 Subject: [PATCH 1/2] Improve canonicalPath method in URIUtil.java Signed-off-by: thesnowgoose --- .../java/org/eclipse/jetty/util/URIUtil.java | 154 ++++-------------- 1 file changed, 34 insertions(+), 120 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index 7f912103ea7..d71bd4c695f 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -20,6 +20,10 @@ package org.eclipse.jetty.util; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.log.Log; @@ -503,130 +507,40 @@ public class URIUtil */ public static String canonicalPath(String path) { - if (path==null || path.length()==0) + if (path == null || path.isEmpty() || !path.contains(".")) return path; - int end=path.length(); - int start = path.lastIndexOf('/', end); - - search: - while (end>0) - { - switch(end-start) - { - case 2: // possible single dot - if (path.charAt(start+1)!='.') - break; - break search; - case 3: // possible double dot - if (path.charAt(start+1)!='.' || path.charAt(start+2)!='.') - break; - break search; - } - - end=start; - start=path.lastIndexOf('/',end-1); - } - - // If we have checked the entire string - if (start>=end) - return path; - - StringBuilder buf = new StringBuilder(path); - int delStart=-1; - int delEnd=-1; - int skip=0; - - while (end>0) - { - switch(end-start) - { - case 2: // possible single dot - if (buf.charAt(start+1)!='.') - { - if (skip>0 && --skip==0) - { - delStart=start>=0?start:0; - if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - break; - } - - if(start<0 && buf.length()>2 && buf.charAt(1)=='/' && buf.charAt(2)=='/') - break; - - if(delEnd<0) - delEnd=end; - delStart=start; - if (delStart<0 || delStart==0&&buf.charAt(delStart)=='/') - { - delStart++; - if (delEnd=0 && buf.charAt(start)!='/') - start--; - continue; - - case 3: // possible double dot - if (buf.charAt(start+1)!='.' || buf.charAt(start+2)!='.') - { - if (skip>0 && --skip==0) - { delStart=start>=0?start:0; - if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - break; - } - - delStart=start; - if (delEnd<0) - delEnd=end; - - skip++; - end=start--; - while (start>=0 && buf.charAt(start)!='/') - start--; - continue; - - default: - if (skip>0 && --skip==0) - { - delStart=start>=0?start:0; - if(delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - } - - // Do the delete - if (skip<=0 && delStart>=0 && delEnd>=delStart) - { - buf.delete(delStart,delEnd); - delStart=delEnd=-1; - if (skip>0) - delEnd=end; - } - - end=start--; - while (start>=0 && buf.charAt(start)!='/') - start--; - } - - // Too many .. - if (skip>0) + if(path.startsWith("/..")) return null; - - // Do the delete - if (delEnd>=0) - buf.delete(delStart,delEnd); - return buf.toString(); + List directories = new LinkedList<>(); + Collections.addAll(directories, path.split("(?<=\\/)")); + + for(ListIterator iterator = directories.listIterator(); iterator.hasNext();) + { + switch (iterator.next()) { + case "./": + case ".": + if (iterator.hasNext() && directories.get(iterator.nextIndex()).equals("/")) { + break; + } + iterator.remove(); + break; + case "../": + case "..": + if(iterator.previousIndex() == 0) { + return null; + } + iterator.remove(); + iterator.previous(); + iterator.remove(); + break; + } + } + if (directories.isEmpty() && path.startsWith("/")) + return null; + + return String.join("", directories); } /* ------------------------------------------------------------ */ From f1cd6f6e4d26c09ea515ecd28521bef61da9e575 Mon Sep 17 00:00:00 2001 From: thesnowgoose Date: Tue, 29 Mar 2016 18:01:55 -0700 Subject: [PATCH 2/2] Improve canonicalPath method in URIUtil.java Signed-off-by: thesnowgoose --- jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index d71bd4c695f..267e9568d31 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.regex.Pattern; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.log.Log; @@ -53,6 +54,7 @@ public class URIUtil public static final String HTTP_COLON="http:"; public static final String HTTPS="https"; public static final String HTTPS_COLON="https:"; + private static final Pattern __PATH_SPLIT = Pattern.compile("(?<=\\/)"); // Use UTF-8 as per http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars public static final Charset __CHARSET=StandardCharsets.UTF_8 ; @@ -514,7 +516,7 @@ public class URIUtil return null; List directories = new LinkedList<>(); - Collections.addAll(directories, path.split("(?<=\\/)")); + Collections.addAll(directories, __PATH_SPLIT.split(path)); for(ListIterator iterator = directories.listIterator(); iterator.hasNext();) {