[英]Java file canonicalPath with tailing '.. ' leads to inconsistent behavior
我正在調查一些與pathTraversal相關的安全機制,並遇到了java.io.File.getCanonicalPath()的奇怪行為。 我認為CanonicalPath將始終代表抽象底層文件的真正唯一路徑。 但是,如果文件名包含兩個點后跟一個空格,則CanonicalPath似乎不再代表正確的路徑。
這是一個例子:
File root = new File("c:/git/");
String relative = ".. /.. \\";
File concatFile = new File (root.getCanonicalPath(), relative);
System.out.println("ConcatFileAbsolute: '" + concatFile.getAbsolutePath() + "'");
System.out.println("ConcatFileCanonical: '" + concatFile.getCanonicalPath() + "'");
File canonFile = new File(concatFile.getCanonicalPath());
System.out.println("\ncanonFileCanonical: '" + canonFile.getCanonicalPath() + "'");
System.out.println("canonFileAbsolute: '" + canonFile.getAbsolutePath() + "'");
System.out.println("canonFileName: '" + canonFile.getName() + "'\n");
for (File file : canonFile.listFiles()) {
System.out.println("canon: '" + file.getCanonicalPath() + "' - absolute: '" + file.getAbsolutePath()+ "'");
}
控制台輸出:
ConcatFileAbsolute: 'C:\git\.. \.. '
ConcatFileCanonical: 'C:\git\.. \'
canonFileCanonical: 'C:\git\'
canonFileAbsolute: 'C:\git\.. '
canonFileName: '.. '
canon: 'C:\git\.. \$Recycle.Bin' - absolute: 'C:\git\.. \$Recycle.Bin'
canon: 'C:\git\.. \.m2' - absolute: 'C:\git\.. \.m2'
canon: 'C:\git\.. \boot' - absolute: 'C:\git\.. \boot'
...other content of C:/
正如您所看到的,雖然canonFile的canonicalPath清楚地表明它在C:\\ git \\中的位置,但.listFiles列出了C:中的所有文件。
只有在我使用新的File(String,String)構造函數時才會發生這種情況。 如果我將第三行更改為File concatFile = new File(root.getCanonicalPath()+ relative); 然后輸出符合預期:
ConcatFileAbsolute: 'C:\git.. \.. '
ConcatFileCanonical: 'C:\git\'
- The following output then lists files under C:\git\
我不知道在unix類系統上這種行為是否類似。
有人可以澄清這種行為嗎? 這是有意的嗎?
先謝謝!
恭喜! 您發現了WinAPI可能存在的錯誤(或功能?)。
更具體地說,您的問題可以簡化為一行代碼:
為什么new File("c:\\\\temp\\\\.. ").getCanonicalPath()
返回c:\\temp\\
而不是c:\\
?
答案很簡單:因為經過尾礦空間的..
(是的,你是上面提到的)。
答案很長:如果我們將查看底層類的Java實現,我們會發現對於Windows它是WinNTFileSystem
類,其中本機方法canonicalize0("c:\\\\temp\\\\.. ")
返回此破壞的值。 為什么? 為了測試它,我編寫了簡單的VBS代碼來測試Win API:
Dim folderName
folderName = "c:\temp\.. "
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim fullpath
fullpath = fso.GetAbsolutePathName(folderName)
WScript.Echo "fullpath: " & fullpath
它給出了完全相同的結果:
fullpath: C:\temp
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.