-
Bug
-
Resolution: Fixed
-
P4
-
8u25, 17, 21, 22
-
b17
-
x86, x86_64
-
linux, linux_ubuntu, os_x
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8338391 | 21.0.5 | Aleksey Shipilev | P4 | Resolved | Fixed | b04 |
FULL PRODUCT VERSION :
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 14.10, x86_64
A DESCRIPTION OF THE PROBLEM :
/tmp/x $ cat Test.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class Test
{
public static void main(final String... args)
throws IOException
{
final Path a = Paths.get("a");
final Path b = Paths.get("b");
Files.copy(a, b, StandardCopyOption.REPLACE_EXISTING);
}
}
/tmp/x $ ls
Test.java
/tmp/x $ touch a b
/tmp/x $ chmod 0 a
/tmp/x $ cp a b
cp: cannot open ‘a’ for reading: Permission denied
/tmp/x $ javac Test.java
/tmp/x $ java Test
Exception in thread "main" java.nio.file.AccessDeniedException: a
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixCopyFile.copyFile(UnixCopyFile.java:230)
at sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:581)
at sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:253)
at java.nio.file.Files.copy(Files.java:1274)
at Test.main(Test.java:15)
/tmp/x $ ls
a Test.class Test.java
/tmp/x $
The rundown is pretty simple:
* I purposefully set file "a" so that I cannot read from it;
* I invoke the cp command to copy the contents of "a" to "b": it fails: however, "b" is left intact;
* I now try and invoke Files.copy(), specifying that I want to replace the destination;
* "a" fails to be read and the exception is correctly reported (AccessDeniedException);
* BUT... b is GONE.
Now, thanks to Michael Rasmussen (michael.rasmussen@zeroturnaround.com), I have two more pieces of information:
* this bug DOES NOT happens on Windows;
* it seems to be isolated to a specific section of code in the UnixFileSystemProvider and not limited to Linux. Original link was:
http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java#l556
This means that the provider only checks for the destination file's existence; however, it fails to check _beforehand_ that the source path from which to copy is readable at all.
Note that here both the source and destination (the "victim" as I like to call it) are regular files; I have not checked the behavior in the following cases:
* the source is a directory;
* the destination is an empty directory (though, from the code, it seems obvious that it will be rmdir()ed; however I fail to see what exception would be thrown if the directory were not empty).
ADDITIONAL REGRESSION INFORMATION:
Unsure; I have only stumbled upon this bug a few hours ago; however it is pretty critical.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Just adapt the bug text to your own Unix system
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The destination file is not deleted; or, if it is an empty directory, it is not removed
ACTUAL -
the destination file is removed
ERROR MESSAGES/STACK TRACES THAT OCCUR :
The expected one, see bug report
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See test case.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None...
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 14.10, x86_64
A DESCRIPTION OF THE PROBLEM :
/tmp/x $ cat Test.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class Test
{
public static void main(final String... args)
throws IOException
{
final Path a = Paths.get("a");
final Path b = Paths.get("b");
Files.copy(a, b, StandardCopyOption.REPLACE_EXISTING);
}
}
/tmp/x $ ls
Test.java
/tmp/x $ touch a b
/tmp/x $ chmod 0 a
/tmp/x $ cp a b
cp: cannot open ‘a’ for reading: Permission denied
/tmp/x $ javac Test.java
/tmp/x $ java Test
Exception in thread "main" java.nio.file.AccessDeniedException: a
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixCopyFile.copyFile(UnixCopyFile.java:230)
at sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:581)
at sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:253)
at java.nio.file.Files.copy(Files.java:1274)
at Test.main(Test.java:15)
/tmp/x $ ls
a Test.class Test.java
/tmp/x $
The rundown is pretty simple:
* I purposefully set file "a" so that I cannot read from it;
* I invoke the cp command to copy the contents of "a" to "b": it fails: however, "b" is left intact;
* I now try and invoke Files.copy(), specifying that I want to replace the destination;
* "a" fails to be read and the exception is correctly reported (AccessDeniedException);
* BUT... b is GONE.
Now, thanks to Michael Rasmussen (michael.rasmussen@zeroturnaround.com), I have two more pieces of information:
* this bug DOES NOT happens on Windows;
* it seems to be isolated to a specific section of code in the UnixFileSystemProvider and not limited to Linux. Original link was:
http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java#l556
This means that the provider only checks for the destination file's existence; however, it fails to check _beforehand_ that the source path from which to copy is readable at all.
Note that here both the source and destination (the "victim" as I like to call it) are regular files; I have not checked the behavior in the following cases:
* the source is a directory;
* the destination is an empty directory (though, from the code, it seems obvious that it will be rmdir()ed; however I fail to see what exception would be thrown if the directory were not empty).
ADDITIONAL REGRESSION INFORMATION:
Unsure; I have only stumbled upon this bug a few hours ago; however it is pretty critical.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Just adapt the bug text to your own Unix system
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The destination file is not deleted; or, if it is an empty directory, it is not removed
ACTUAL -
the destination file is removed
ERROR MESSAGES/STACK TRACES THAT OCCUR :
The expected one, see bug report
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
See test case.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
None...
- backported by
-
JDK-8338391 (fs) Files.copy(foo, bar, REPLACE_EXISTING) deletes bar even if foo is not readable
- Resolved
- relates to
-
JDK-8317128 java/nio/file/Files/CopyAndMove.java failed with AccessDeniedException
- Resolved
- links to
-
Commit openjdk/jdk/36ac8390
-
Commit(master) openjdk/jdk21u-dev/590715f4
-
Review openjdk/jdk/15501
-
Review(master) openjdk/jdk21u-dev/863
(1 links to)