diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 9b0c263a2..63243744c 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -278,6 +278,7 @@ Matthew Warman Matthew Watson Matthew Yanos Matthias Bhend +Michael Barker Michael Bayne Michael Clarke Michael Davey diff --git a/WHATSNEW b/WHATSNEW index 4253d63c6..c2c3da6af 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -27,6 +27,11 @@ Fixed bugs: an incorrect compression level for a zip entry. This is now fixed. Bugzilla Report 62686 + * A filesystem "loop" caused due to symbolic links could trigger an + out of memory error in the org.apache.tools.ant.DirectoryScanner + This has now been fixed. + Bugzilla Report 62849 + Other changes: -------------- * generatekey task now supports SubjectAlternativeName during key diff --git a/contributors.xml b/contributors.xml index ebf03ee77..3c95e6e01 100644 --- a/contributors.xml +++ b/contributors.xml @@ -1155,6 +1155,10 @@ Matthias Bhend + + Michael + Barker + Michael Bayne diff --git a/src/etc/testcases/core/directoryscanner.xml b/src/etc/testcases/core/directoryscanner.xml index 7e8683a4a..71eb88bf7 100644 --- a/src/etc/testcases/core/directoryscanner.xml +++ b/src/etc/testcases/core/directoryscanner.xml @@ -38,4 +38,9 @@ + + + + + diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 71465dbc3..289239b78 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -1237,6 +1237,18 @@ public class DirectoryScanner final String name = vpath + newFile; final TokenizedPath newPath = new TokenizedPath(path, newFile); final File file = new File(dir, newFile); + + try { + // check if it's a filesystem "loop" due to symbolic links + if (FileUtils.getFileUtils().isLeadingPath(file.getAbsoluteFile(), + dir.getAbsoluteFile(), true)) { + continue; + } + } catch (IOException e) { + System.err.println("Failed to determine if " + file + " causes a " + + "filesystem loop due to symbolic link; continuing"); + } + final String[] children = file.list(); if (children == null || (children.length == 0 && file.isFile())) { if (isIncluded(newPath)) { diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java index 22eefa132..bf810e869 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Delete.java +++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java @@ -18,6 +18,7 @@ package org.apache.tools.ant.taskdefs; +import java.io.IOException; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; @@ -814,7 +815,19 @@ public class Delete extends MatchingTask { } for (String s : list) { File f = new File(d, s); - if (f.isDirectory()) { + + boolean isFsLoop = false; + + try { + isFsLoop = Files.isSymbolicLink(f.toPath()) && + FileUtils.getFileUtils().isLeadingPath(f.getAbsoluteFile(), + d.getAbsoluteFile(), true); + } catch (IOException e) { + log("Failed to check if " + f + " causes a filesystem loop due to " + + "symbolic link; continuing"); + } + + if (f.isDirectory() && !isFsLoop) { removeDir(f); } else { log("Deleting " + f.getAbsolutePath(), quiet ? Project.MSG_VERBOSE : verbosity); diff --git a/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java b/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java index 6dab26c11..e332a9c83 100644 --- a/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java +++ b/src/tests/junit/org/apache/tools/ant/DirectoryScannerTest.java @@ -130,6 +130,20 @@ public class DirectoryScannerTest { new String[] {"alpha/beta/gamma"}); } + @Test + public void testAllowRecursiveSymlinks() { + + assumeTrue("Current system does not support Symlinks", supportsSymlinks); + + buildRule.getProject().executeTarget("symlink-nested-setup"); + DirectoryScanner ds = new DirectoryScanner(); + ds.setBasedir(new File(buildRule.getProject().getProperty("output"))); + ds.setIncludes(new String[] {"alpha/beta/gamma/"}); + ds.scan(); + compareFiles(ds, new String[] {"alpha/beta/gamma/gamma.xml"}, + new String[] {"alpha/beta/gamma"}); + } + @Test public void testProhibitSymlinks() { assumeTrue("Current system does not support Symlinks", supportsSymlinks);