diff --git a/CHANGELOG.md b/CHANGELOG.md index c66f19075..e44903d7b 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.17.M1 (2023-03-29) +# 5.8.17.M1 (2023-03-31) ### 🐣新特性 * 【core 】 SerializeUtil.deserialize增加白名单类,避免RCE vulnerability(issue#3021@Github) @@ -11,6 +11,7 @@ ### 🐞Bug修复 * 【core 】 CollUtil.split优化切割列表参数判断,避免OOM(pr#3026@Github) +* 【core 】 修复FileUtil.move传入相同目录或子目录丢失源目录的问题(pr#3032@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.16 (2023-03-26) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java index ef7acd9be..b2eca2ca8 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/file/PathMover.java @@ -4,6 +4,7 @@ import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.file.visitor.MoveVisitor; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import java.io.IOException; import java.nio.file.*; @@ -80,17 +81,21 @@ public class PathMover { Path target = this.target; final CopyOption[] options = this.options; + if (PathUtil.isSub(src, target)) { + if(Files.exists(target) && PathUtil.equals(src, target)){ + // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 + return target; + } + + // 当用户将文件夹拷贝到其子文件夹时,报错 + throw new IllegalArgumentException(StrUtil.format("Target [{}] is sub path of src [{}]!", target, src)); + } + if (PathUtil.isDirectory(target)) { // 创建子路径的情况,1是目标是目录,需要移动到目录下,2是目标不能存在,自动创建目录 target = target.resolve(src.getFileName()); } - // issue#2893 target 不存在导致NoSuchFileException - if (Files.exists(target) && PathUtil.equals(src, target)) { - // issue#2845,当用户传入目标路径与源路径一致时,直接返回,否则会导致删除风险。 - return target; - } - // 自动创建目标的父目录 PathUtil.mkParentDirs(target); try { diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java index 350bae0a0..caf2117dd 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java @@ -22,7 +22,7 @@ public class FileUtilTest { @Test(expected = IllegalArgumentException.class) public void fileTest() { - File file = FileUtil.file("d:/aaa", "bbb"); + final File file = FileUtil.file("d:/aaa", "bbb"); Assert.assertNotNull(file); // 构建目录中出现非子目录抛出异常 @@ -33,9 +33,9 @@ public class FileUtilTest { @Test public void getAbsolutePathTest() { - String absolutePath = FileUtil.getAbsolutePath("LICENSE-junit.txt"); + final String absolutePath = FileUtil.getAbsolutePath("LICENSE-junit.txt"); Assert.assertNotNull(absolutePath); - String absolutePath2 = FileUtil.getAbsolutePath(absolutePath); + final String absolutePath2 = FileUtil.getAbsolutePath(absolutePath); Assert.assertNotNull(absolutePath2); Assert.assertEquals(absolutePath, absolutePath2); @@ -56,7 +56,7 @@ public class FileUtilTest { @Ignore public void delTest() { // 删除一个不存在的文件,应返回true - boolean result = FileUtil.del("e:/Hutool_test_3434543533409843.txt"); + final boolean result = FileUtil.del("e:/Hutool_test_3434543533409843.txt"); Assert.assertTrue(result); } @@ -64,7 +64,7 @@ public class FileUtilTest { @Ignore public void delTest2() { // 删除一个不存在的文件,应返回true - boolean result = FileUtil.del(Paths.get("e:/Hutool_test_3434543533409843.txt")); + final boolean result = FileUtil.del(Paths.get("e:/Hutool_test_3434543533409843.txt")); Assert.assertTrue(result); } @@ -82,8 +82,8 @@ public class FileUtilTest { @Test public void copyTest() { - File srcFile = FileUtil.file("hutool.jpg"); - File destFile = FileUtil.file("hutool.copy.jpg"); + final File srcFile = FileUtil.file("hutool.jpg"); + final File destFile = FileUtil.file("hutool.copy.jpg"); FileUtil.copy(srcFile, destFile, true); @@ -94,8 +94,8 @@ public class FileUtilTest { @Test @Ignore public void copyFilesFromDirTest() { - File srcFile = FileUtil.file("D:\\驱动"); - File destFile = FileUtil.file("d:\\驱动备份"); + final File srcFile = FileUtil.file("D:\\驱动"); + final File destFile = FileUtil.file("d:\\驱动备份"); FileUtil.copyFilesFromDir(srcFile, destFile, true); } @@ -103,8 +103,8 @@ public class FileUtilTest { @Test @Ignore public void copyDirTest() { - File srcFile = FileUtil.file("D:\\test"); - File destFile = FileUtil.file("E:\\"); + final File srcFile = FileUtil.file("D:\\test"); + final File destFile = FileUtil.file("E:\\"); FileUtil.copy(srcFile, destFile, true); } @@ -112,26 +112,42 @@ public class FileUtilTest { @Test @Ignore public void moveDirTest() { - File srcFile = FileUtil.file("E:\\test2"); - File destFile = FileUtil.file("D:\\"); + final File srcFile = FileUtil.file("E:\\test2"); + final File destFile = FileUtil.file("D:\\"); FileUtil.move(srcFile, destFile, true); } + @Test + @Ignore + public void renameToSubTest() { + Assert.assertThrows(IllegalArgumentException.class, ()->{ + // 移动到子目录,报错 + FileUtil.move(FileUtil.file("d:/test/a"), FileUtil.file("d:/test/a/c"), false); + }); + } + + @Test + @Ignore + public void renameSameTest() { + // 目标和源相同,不处理 + FileUtil.move(FileUtil.file("d:/test/a"), FileUtil.file("d:/test/a"), false); + } + @Test public void equalsTest() { // 源文件和目标文件都不存在 - File srcFile = FileUtil.file("d:/hutool.jpg"); - File destFile = FileUtil.file("d:/hutool.jpg"); + final File srcFile = FileUtil.file("d:/hutool.jpg"); + final File destFile = FileUtil.file("d:/hutool.jpg"); - boolean equals = FileUtil.equals(srcFile, destFile); + final boolean equals = FileUtil.equals(srcFile, destFile); Assert.assertTrue(equals); // 源文件存在,目标文件不存在 - File srcFile1 = FileUtil.file("hutool.jpg"); - File destFile1 = FileUtil.file("d:/hutool.jpg"); + final File srcFile1 = FileUtil.file("hutool.jpg"); + final File destFile1 = FileUtil.file("d:/hutool.jpg"); - boolean notEquals = FileUtil.equals(srcFile1, destFile1); + final boolean notEquals = FileUtil.equals(srcFile1, destFile1); Assert.assertFalse(notEquals); } @@ -170,13 +186,13 @@ public class FileUtilTest { @Test public void normalizeHomePathTest() { - String home = FileUtil.getUserHomePath().replace('\\', '/'); + final String home = FileUtil.getUserHomePath().replace('\\', '/'); Assert.assertEquals(home + "/bar/", FileUtil.normalize("~/foo/../bar/")); } @Test public void normalizeHomePathTest2() { - String home = FileUtil.getUserHomePath().replace('\\', '/'); + final String home = FileUtil.getUserHomePath().replace('\\', '/'); // 多个~应该只替换开头的 Assert.assertEquals(home + "/~bar/", FileUtil.normalize("~/foo/../~bar/")); } @@ -194,15 +210,15 @@ public class FileUtilTest { @Test public void doubleNormalizeTest() { - String normalize = FileUtil.normalize("/aa/b:/c"); - String normalize2 = FileUtil.normalize(normalize); + final String normalize = FileUtil.normalize("/aa/b:/c"); + final String normalize2 = FileUtil.normalize(normalize); Assert.assertEquals("/aa/b:/c", normalize); Assert.assertEquals(normalize, normalize2); } @Test public void subPathTest() { - Path path = Paths.get("/aaa/bbb/ccc/ddd/eee/fff"); + final Path path = Paths.get("/aaa/bbb/ccc/ddd/eee/fff"); Path subPath = FileUtil.subPath(path, 5, 4); Assert.assertEquals("eee", subPath.toString()); @@ -248,7 +264,7 @@ public class FileUtilTest { @Test public void getPathEle() { - Path path = Paths.get("/aaa/bbb/ccc/ddd/eee/fff"); + final Path path = Paths.get("/aaa/bbb/ccc/ddd/eee/fff"); Path ele = FileUtil.getPathEle(path, -1); Assert.assertEquals("fff", ele.toString()); @@ -275,8 +291,8 @@ public class FileUtilTest { @Test @Ignore public void listFileNamesInJarTest() { - List names = FileUtil.listFileNames("d:/test/hutool-core-5.1.0.jar!/cn/hutool/core/util "); - for (String name : names) { + final List names = FileUtil.listFileNames("d:/test/hutool-core-5.1.0.jar!/cn/hutool/core/util "); + for (final String name : names) { Console.log(name); } } @@ -284,8 +300,8 @@ public class FileUtilTest { @Test @Ignore public void listFileNamesTest2() { - List names = FileUtil.listFileNames("D:\\m2_repo\\commons-cli\\commons-cli\\1.0\\commons-cli-1.0.jar!org/apache/commons/cli/"); - for (String string : names) { + final List names = FileUtil.listFileNames("D:\\m2_repo\\commons-cli\\commons-cli\\1.0\\commons-cli-1.0.jar!org/apache/commons/cli/"); + for (final String string : names) { Console.log(string); } } @@ -293,8 +309,8 @@ public class FileUtilTest { @Test @Ignore public void loopFilesTest() { - List files = FileUtil.loopFiles("d:/"); - for (File file : files) { + final List files = FileUtil.loopFiles("d:/"); + for (final File file : files) { Console.log(file.getPath()); } } @@ -308,8 +324,8 @@ public class FileUtilTest { @Test @Ignore public void loopFilesWithDepthTest() { - List files = FileUtil.loopFiles(FileUtil.file("d:/m2_repo"), 2, null); - for (File file : files) { + final List files = FileUtil.loopFiles(FileUtil.file("d:/m2_repo"), 2, null); + for (final File file : files) { Console.log(file.getPath()); } } @@ -340,12 +356,12 @@ public class FileUtilTest { @Test public void lastIndexOfSeparatorTest() { - String dir = "d:\\aaa\\bbb\\cc\\ddd"; - int index = FileUtil.lastIndexOfSeparator(dir); + final String dir = "d:\\aaa\\bbb\\cc\\ddd"; + final int index = FileUtil.lastIndexOfSeparator(dir); Assert.assertEquals(13, index); - String file = "ddd.jpg"; - int index2 = FileUtil.lastIndexOfSeparator(file); + final String file = "ddd.jpg"; + final int index2 = FileUtil.lastIndexOfSeparator(file); Assert.assertEquals(-1, index2); } @@ -412,7 +428,7 @@ public class FileUtilTest { @Test public void getWebRootTest() { - File webRoot = FileUtil.getWebRoot(); + final File webRoot = FileUtil.getWebRoot(); Assert.assertNotNull(webRoot); Assert.assertEquals("hutool-core", webRoot.getName()); } @@ -454,35 +470,35 @@ public class FileUtilTest { @Test public void isSubTest() { - File file = new File("d:/test"); - File file2 = new File("d:/test2/aaa"); + final File file = new File("d:/test"); + final File file2 = new File("d:/test2/aaa"); Assert.assertFalse(FileUtil.isSub(file, file2)); } @Test public void isSubRelativeTest() { - File file = new File(".."); - File file2 = new File("."); + final File file = new File(".."); + final File file2 = new File("."); Assert.assertTrue(FileUtil.isSub(file, file2)); } @Test @Ignore public void appendLinesTest(){ - List list = ListUtil.toList("a", "b", "c"); + final List list = ListUtil.toList("a", "b", "c"); FileUtil.appendLines(list, FileUtil.file("d:/test/appendLines.txt"), CharsetUtil.CHARSET_UTF_8); } @Test @Ignore public void createTempFileTest(){ - File nullDirTempFile = FileUtil.createTempFile(); + final File nullDirTempFile = FileUtil.createTempFile(); Assert.assertTrue(nullDirTempFile.exists()); - File suffixDirTempFile = FileUtil.createTempFile(".xlsx",true); + final File suffixDirTempFile = FileUtil.createTempFile(".xlsx",true); Assert.assertEquals("xlsx", FileUtil.getSuffix(suffixDirTempFile)); - File prefixDirTempFile = FileUtil.createTempFile("prefix",".xlsx",true); + final File prefixDirTempFile = FileUtil.createTempFile("prefix",".xlsx",true); Assert.assertTrue(FileUtil.getPrefix(prefixDirTempFile).startsWith("prefix")); }