diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java index b3219cddb..d29a75ef7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java @@ -405,7 +405,7 @@ private void testMaliciousPath(boolean good, boolean secondCheckout, } catch (InvalidPathException e) { if (good) throw e; - assertTrue(e.getMessage().startsWith("Invalid path: ")); + assertTrue(e.getMessage().startsWith("Invalid path")); } } diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index 474b8f349..bb67c127a 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -270,6 +270,10 @@ invalidObject=Invalid {0} {1}:{2} invalidOldIdSent=invalid old id sent invalidPacketLineHeader=Invalid packet line header: {0} invalidPath=Invalid path: {0} +invalidPathContainsSeparator=Invalid path (contains separator ''{0}''): {1} +invalidPathPeriodAtEndWindows=Invalid path (period at end is ignored by Windows): {0} +invalidPathSpaceAtEndWindows=Invalid path (space at end is ignored by Windows): {0} +invalidPathReservedOnWindows=Invalid path (''{0}'' is reserved on Windows): {1} invalidReflogRevision=Invalid reflog revision: {0} invalidRefName=Invalid ref name: {0} invalidRemote=Invalid remote: {0} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java index 103d6183b..f8c8442ff 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -76,6 +76,7 @@ import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; +import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.io.AutoCRLFOutputStream; @@ -306,8 +307,7 @@ public void prescanOneTree() void processEntry(CanonicalTreeParser m, DirCacheBuildIterator i, WorkingTreeIterator f) throws IOException { if (m != null) { - if (!isValidPath(m)) - throw new InvalidPathException(m.getEntryPathString()); + checkValidPath(m); // There is an entry in the merge commit. Means: we want to update // what's currently in the index and working-tree to that one if (i == null) { @@ -522,8 +522,8 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m, String name = walk.getPathString(); - if (m != null && !isValidPath(m)) - throw new InvalidPathException(m.getEntryPathString()); + if (m != null) + checkValidPath(m); if (i == null && m == null && h == null) { // File/Directory conflict case #20 @@ -1157,14 +1157,14 @@ public static void checkoutEntry(final Repository repo, File f, forbidden[i] = Constants.encodeASCII(list[i]); } - private static boolean isValidPath(CanonicalTreeParser t) { + private static void checkValidPath(CanonicalTreeParser t) + throws InvalidPathException { for (CanonicalTreeParser i = t; i != null; i = i.getParent()) - if (!isValidPathSegment(i)) - return false; - return true; + checkValidPathSegment(i); } - private static boolean isValidPathSegment(CanonicalTreeParser t) { + private static void checkValidPathSegment(CanonicalTreeParser t) + throws InvalidPathException { boolean isWindows = SystemReader.getInstance().isWindows(); boolean isOSX = SystemReader.getInstance().isMacOS(); boolean ignCase = isOSX || isWindows; @@ -1177,23 +1177,29 @@ private static boolean isValidPathSegment(CanonicalTreeParser t) { int start = ptr; while (ptr < end) { if (raw[ptr] == '/') - return false; + throw new InvalidPathException( + JGitText.get().invalidPathContainsSeparator, + "/", t.getEntryPathString()); //$NON-NLS-1$ if (isWindows) { if (raw[ptr] == '\\') - return false; + throw new InvalidPathException( + JGitText.get().invalidPathContainsSeparator, + "\\", t.getEntryPathString()); //$NON-NLS-1$ if (raw[ptr] == ':') - return false; + throw new InvalidPathException( + JGitText.get().invalidPathContainsSeparator, + ":", t.getEntryPathString()); //$NON-NLS-1$ } ptr++; } - // '.' and '.'' are invalid here + // '.' and '..' are invalid here if (ptr - start == 1) { if (raw[start] == '.') - return false; + throw new InvalidPathException(t.getEntryPathString()); } else if (ptr - start == 2) { if (raw[start] == '.') if (raw[start + 1] == '.') - return false; + throw new InvalidPathException(t.getEntryPathString()); } else if (ptr - start == 4) { // .git (possibly case insensitive) is disallowed if (raw[start] == '.') @@ -1202,15 +1208,24 @@ private static boolean isValidPathSegment(CanonicalTreeParser t) { || (ignCase && raw[start + 2] == 'I')) if (raw[start + 3] == 't' || (ignCase && raw[start + 3] == 'T')) - return false; + throw new InvalidPathException( + t.getEntryPathString()); } if (isWindows) { // Space or period at end of file name is ignored by Windows. // Treat this as a bad path for now. We may want to handle // this as case insensitivity in the future. - if (ptr > 0) - if (raw[ptr - 1] == '.' || raw[ptr - 1] == ' ') - return false; + if (ptr > 0) { + if (raw[ptr - 1] == '.') + throw new InvalidPathException( + JGitText.get().invalidPathPeriodAtEndWindows, + t.getEntryPathString()); + if (raw[ptr - 1] == ' ') + throw new InvalidPathException( + JGitText.get().invalidPathSpaceAtEndWindows, + t.getEntryPathString()); + } + int i; // Bad names, eliminate suffix first for (i = start; i < ptr; ++i) @@ -1228,13 +1243,14 @@ private static boolean isValidPathSegment(CanonicalTreeParser t) { break; } if (k == len) - return false; + throw new InvalidPathException( + JGitText.get().invalidPathReservedOnWindows, + RawParseUtils.decode(forbidden[j]), t + .getEntryPathString()); } } } } - - return true; } private static byte toUpper(byte b) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/InvalidPathException.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/InvalidPathException.java index 698636c8c..50d1c4ca3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/InvalidPathException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/InvalidPathException.java @@ -60,6 +60,10 @@ public class InvalidPathException extends IllegalArgumentException { * @param path */ public InvalidPathException(String path) { - super(MessageFormat.format(JGitText.get().invalidPath, path)); + this(JGitText.get().invalidPath, path); + } + + InvalidPathException(String messagePattern, Object... arguments) { + super(MessageFormat.format(messagePattern, arguments)); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index b2c27a483..f9700a1ff 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -332,6 +332,10 @@ public static JGitText get() { /***/ public String invalidOldIdSent; /***/ public String invalidPacketLineHeader; /***/ public String invalidPath; + /***/ public String invalidPathContainsSeparator; + /***/ public String invalidPathPeriodAtEndWindows; + /***/ public String invalidPathSpaceAtEndWindows; + /***/ public String invalidPathReservedOnWindows; /***/ public String invalidReflogRevision; /***/ public String invalidRefName; /***/ public String invalidRemote;