| /* | |
| * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* @test | |
| * @bug 8003992 8027155 | |
| * @summary Test a file whose path name is embedded with NUL character, and | |
| * ensure it is handled correctly. | |
| * @author Dan Xu | |
| */ | |
| import java.io.File; | |
| import java.io.FileFilter; | |
| import java.io.FileInputStream; | |
| import java.io.FileOutputStream; | |
| import java.io.RandomAccessFile; | |
| import java.io.FileNotFoundException; | |
| import java.io.FilenameFilter; | |
| import java.io.IOException; | |
| import java.net.MalformedURLException; | |
| import java.nio.file.InvalidPathException; | |
| import java.io.ByteArrayInputStream; | |
| import java.io.ByteArrayOutputStream; | |
| import java.io.ObjectOutputStream; | |
| import java.io.ObjectInputStream; | |
| public class NulFile { | |
| private static final char CHAR_NUL = '\u0000'; | |
| private static final String ExceptionMsg = "Invalid file path"; | |
| public static void main(String[] args) { | |
| testFile(); | |
| testFileInUnix(); | |
| testFileInWindows(); | |
| testTempFile(); | |
| } | |
| private static void testFile() { | |
| test(new File(new StringBuilder().append(CHAR_NUL).toString())); | |
| test(new File( | |
| new StringBuilder().append("").append(CHAR_NUL).toString())); | |
| test(new File( | |
| new StringBuilder().append(CHAR_NUL).append("").toString())); | |
| } | |
| private static void testFileInUnix() { | |
| String osName = System.getProperty("os.name"); | |
| if (osName.startsWith("Windows")) | |
| return; | |
| String unixFile = "/"; | |
| test(unixFile); | |
| unixFile = "//"; | |
| test(unixFile); | |
| unixFile = "data/info"; | |
| test(unixFile); | |
| unixFile = "/data/info"; | |
| test(unixFile); | |
| unixFile = "//data//info"; | |
| test(unixFile); | |
| } | |
| private static void testFileInWindows() { | |
| String osName = System.getProperty("os.name"); | |
| if (!osName.startsWith("Windows")) | |
| return; | |
| String windowsFile = "\\"; | |
| test(windowsFile); | |
| windowsFile = "\\\\"; | |
| test(windowsFile); | |
| windowsFile = "/"; | |
| test(windowsFile); | |
| windowsFile = "//"; | |
| test(windowsFile); | |
| windowsFile = "/\\"; | |
| test(windowsFile); | |
| windowsFile = "\\/"; | |
| test(windowsFile); | |
| windowsFile = "data\\info"; | |
| test(windowsFile); | |
| windowsFile = "\\data\\info"; | |
| test(windowsFile); | |
| windowsFile = "\\\\server\\data\\info"; | |
| test(windowsFile); | |
| windowsFile = "z:data\\info"; | |
| test(windowsFile); | |
| windowsFile = "z:\\data\\info"; | |
| test(windowsFile); | |
| } | |
| private static void test(final String name) { | |
| int length = name.length(); | |
| for (int i = 0; i <= length; i++) { | |
| StringBuilder sbName = new StringBuilder(name); | |
| sbName.insert(i, CHAR_NUL); | |
| String curName = sbName.toString(); | |
| // test File(String parent, String child) | |
| File testFile = new File(curName, "child"); | |
| test(testFile); | |
| testFile = new File("parent", curName); | |
| test(testFile); | |
| // test File(String pathname) | |
| testFile = new File(curName); | |
| test(testFile); | |
| // test File(File parent, String child) | |
| testFile = new File(new File(curName), "child"); | |
| test(testFile); | |
| testFile = new File(new File("parent"), curName); | |
| test(testFile); | |
| // test FileInputStream | |
| testFileInputStream(curName); | |
| // test FileOutputStream | |
| testFileOutputStream(curName); | |
| // test RandomAccessFile | |
| testRandomAccessFile(curName); | |
| } | |
| } | |
| private static void testFileInputStream(final String str) { | |
| boolean exceptionThrown = false; | |
| FileInputStream is = null; | |
| try { | |
| is = new FileInputStream(str); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("FileInputStream constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (is != null) { | |
| throw new RuntimeException("FileInputStream constructor" | |
| + " should fail"); | |
| } | |
| exceptionThrown = false; | |
| is = null; | |
| try { | |
| is = new FileInputStream(new File(str)); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("FileInputStream constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (is != null) { | |
| throw new RuntimeException("FileInputStream constructor" | |
| + " should fail"); | |
| } | |
| } | |
| private static void testFileOutputStream(final String str) { | |
| boolean exceptionThrown = false; | |
| FileOutputStream os = null; | |
| try { | |
| os = new FileOutputStream(str); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("FileOutputStream constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (os != null) { | |
| throw new RuntimeException("FileOutputStream constructor" | |
| + " should fail"); | |
| } | |
| exceptionThrown = false; | |
| os = null; | |
| try { | |
| os = new FileOutputStream(new File(str)); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("FileOutputStream constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (os != null) { | |
| throw new RuntimeException("FileOutputStream constructor" | |
| + " should fail"); | |
| } | |
| } | |
| private static void testRandomAccessFile(final String str) { | |
| boolean exceptionThrown = false; | |
| RandomAccessFile raf = null; | |
| String[] modes = {"r", "rw", "rws", "rwd"}; | |
| for (String mode : modes) { | |
| try { | |
| raf = new RandomAccessFile(str, mode); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("RandomAccessFile constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (raf != null) { | |
| throw new RuntimeException("RandomAccessFile constructor" | |
| + " should fail"); | |
| } | |
| exceptionThrown = false; | |
| raf = null; | |
| try { | |
| raf = new RandomAccessFile(new File(str), mode); | |
| } catch (FileNotFoundException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("RandomAccessFile constructor" | |
| + " should throw FileNotFoundException"); | |
| } | |
| if (raf != null) { | |
| throw new RuntimeException("RandomAccessFile constructor" | |
| + " should fail"); | |
| } | |
| } | |
| } | |
| private static void test(File testFile) { | |
| test(testFile, false); | |
| // test serialization | |
| testSerialization(testFile); | |
| } | |
| @SuppressWarnings("deprecation") | |
| private static void test(File testFile, boolean derived) { | |
| boolean exceptionThrown = false; | |
| if (testFile == null) { | |
| throw new RuntimeException("test file should not be null."); | |
| } | |
| // getPath() | |
| if (testFile.getPath().indexOf(CHAR_NUL) < 0) { | |
| throw new RuntimeException( | |
| "File path should contain Nul character"); | |
| } | |
| // getAbsolutePath() | |
| if (testFile.getAbsolutePath().indexOf(CHAR_NUL) < 0) { | |
| throw new RuntimeException( | |
| "File absolute path should contain Nul character"); | |
| } | |
| // getAbsoluteFile() | |
| File derivedAbsFile = testFile.getAbsoluteFile(); | |
| if (derived) { | |
| if (derivedAbsFile.getPath().indexOf(CHAR_NUL) < 0) { | |
| throw new RuntimeException( | |
| "Derived file path should also contain Nul character"); | |
| } | |
| } else { | |
| test(derivedAbsFile, true); | |
| } | |
| // getCanonicalPath() | |
| try { | |
| exceptionThrown = false; | |
| testFile.getCanonicalPath(); | |
| } catch (IOException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException( | |
| "getCanonicalPath() should throw IOException with" | |
| + " message \"" + ExceptionMsg + "\""); | |
| } | |
| // getCanonicalFile() | |
| try { | |
| exceptionThrown = false; | |
| testFile.getCanonicalFile(); | |
| } catch (IOException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException( | |
| "getCanonicalFile() should throw IOException with" | |
| + " message \"" + ExceptionMsg + "\""); | |
| } | |
| // toURL() | |
| try { | |
| exceptionThrown = false; | |
| testFile.toURL(); | |
| } catch (MalformedURLException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("toURL() should throw IOException with" | |
| + " message \"" + ExceptionMsg + "\""); | |
| } | |
| // canRead() | |
| if (testFile.canRead()) | |
| throw new RuntimeException("File should not be readable"); | |
| // canWrite() | |
| if (testFile.canWrite()) | |
| throw new RuntimeException("File should not be writable"); | |
| // exists() | |
| if (testFile.exists()) | |
| throw new RuntimeException("File should not be existed"); | |
| // isDirectory() | |
| if (testFile.isDirectory()) | |
| throw new RuntimeException("File should not be a directory"); | |
| // isFile() | |
| if (testFile.isFile()) | |
| throw new RuntimeException("File should not be a file"); | |
| // isHidden() | |
| if (testFile.isHidden()) | |
| throw new RuntimeException("File should not be hidden"); | |
| // lastModified() | |
| if (testFile.lastModified() != 0L) | |
| throw new RuntimeException("File last modified time should be 0L"); | |
| // length() | |
| if (testFile.length() != 0L) | |
| throw new RuntimeException("File length should be 0L"); | |
| // createNewFile() | |
| try { | |
| exceptionThrown = false; | |
| testFile.createNewFile(); | |
| } catch (IOException ex) { | |
| if (ExceptionMsg.equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException( | |
| "createNewFile() should throw IOException with" | |
| + " message \"" + ExceptionMsg + "\""); | |
| } | |
| // delete() | |
| if (testFile.delete()) | |
| throw new RuntimeException("Delete operation should fail"); | |
| // list() | |
| if (testFile.list() != null) | |
| throw new RuntimeException("File list() should return null"); | |
| // list(FilenameFilter) | |
| FilenameFilter fnFilter = new FilenameFilter() { | |
| @Override | |
| public boolean accept(File dir, String name) { | |
| return false; | |
| } | |
| }; | |
| if (testFile.list(fnFilter) != null) { | |
| throw new RuntimeException("File list(FilenameFilter) should" | |
| + " return null"); | |
| } | |
| // listFiles() | |
| if (testFile.listFiles() != null) | |
| throw new RuntimeException("File listFiles() should return null"); | |
| // listFiles(FilenameFilter) | |
| if (testFile.listFiles(fnFilter) != null) { | |
| throw new RuntimeException("File listFiles(FilenameFilter)" | |
| + " should return null"); | |
| } | |
| // listFiles(FileFilter) | |
| FileFilter fFilter = new FileFilter() { | |
| @Override | |
| public boolean accept(File file) { | |
| return false; | |
| } | |
| }; | |
| if (testFile.listFiles(fFilter) != null) { | |
| throw new RuntimeException("File listFiles(FileFilter)" | |
| + " should return null"); | |
| } | |
| // mkdir() | |
| if (testFile.mkdir()) { | |
| throw new RuntimeException("File should not be able to" | |
| + " create directory"); | |
| } | |
| // mkdirs() | |
| if (testFile.mkdirs()) { | |
| throw new RuntimeException("File should not be able to" | |
| + " create directories"); | |
| } | |
| // renameTo(File) | |
| if (testFile.renameTo(new File("dest"))) | |
| throw new RuntimeException("File rename should fail"); | |
| if (new File("dest").renameTo(testFile)) | |
| throw new RuntimeException("File rename should fail"); | |
| try { | |
| exceptionThrown = false; | |
| testFile.renameTo(null); | |
| } catch (NullPointerException ex) { | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("File rename should thrown NPE"); | |
| } | |
| // setLastModified(long) | |
| if (testFile.setLastModified(0L)) { | |
| throw new RuntimeException("File should fail to set" | |
| + " last modified time"); | |
| } | |
| try { | |
| exceptionThrown = false; | |
| testFile.setLastModified(-1); | |
| } catch (IllegalArgumentException ex) { | |
| if ("Negative time".equals(ex.getMessage())) | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("File should fail to set" | |
| + " last modified time with message \"Negative time\""); | |
| } | |
| // setReadOnly() | |
| if (testFile.setReadOnly()) | |
| throw new RuntimeException("File should fail to set read-only"); | |
| // setWritable(boolean writable, boolean ownerOnly) | |
| if (testFile.setWritable(true, true)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| if (testFile.setWritable(true, false)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| if (testFile.setWritable(false, true)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| if (testFile.setWritable(false, false)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| // setWritable(boolean writable) | |
| if (testFile.setWritable(false)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| if (testFile.setWritable(true)) | |
| throw new RuntimeException("File should fail to set writable"); | |
| // setReadable(boolean readable, boolean ownerOnly) | |
| if (testFile.setReadable(true, true)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| if (testFile.setReadable(true, false)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| if (testFile.setReadable(false, true)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| if (testFile.setReadable(false, false)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| // setReadable(boolean readable) | |
| if (testFile.setReadable(false)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| if (testFile.setReadable(true)) | |
| throw new RuntimeException("File should fail to set readable"); | |
| // setExecutable(boolean executable, boolean ownerOnly) | |
| if (testFile.setExecutable(true, true)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| if (testFile.setExecutable(true, false)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| if (testFile.setExecutable(false, true)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| if (testFile.setExecutable(false, false)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| // setExecutable(boolean executable) | |
| if (testFile.setExecutable(false)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| if (testFile.setExecutable(true)) | |
| throw new RuntimeException("File should fail to set executable"); | |
| // canExecute() | |
| if (testFile.canExecute()) | |
| throw new RuntimeException("File should not be executable"); | |
| // getTotalSpace() | |
| if (testFile.getTotalSpace() != 0L) | |
| throw new RuntimeException("The total space should be 0L"); | |
| // getFreeSpace() | |
| if (testFile.getFreeSpace() != 0L) | |
| throw new RuntimeException("The free space should be 0L"); | |
| // getUsableSpace() | |
| if (testFile.getUsableSpace() != 0L) | |
| throw new RuntimeException("The usable space should be 0L"); | |
| // compareTo(File null) | |
| try { | |
| exceptionThrown = false; | |
| testFile.compareTo(null); | |
| } catch (NullPointerException ex) { | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("compareTo(null) should throw NPE"); | |
| } | |
| // toString() | |
| if (testFile.toString().indexOf(CHAR_NUL) < 0) { | |
| throw new RuntimeException( | |
| "File path should contain Nul character"); | |
| } | |
| // toPath() | |
| try { | |
| exceptionThrown = false; | |
| testFile.toPath(); | |
| } catch (InvalidPathException ex) { | |
| exceptionThrown = true; | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("toPath() should throw" | |
| + " InvalidPathException"); | |
| } | |
| } | |
| private static void testSerialization(File testFile) { | |
| String path = testFile.getPath(); | |
| try { | |
| // serialize test file | |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
| ObjectOutputStream oos = new ObjectOutputStream(baos); | |
| oos.writeObject(testFile); | |
| oos.close(); | |
| // deserialize test file | |
| byte[] bytes = baos.toByteArray(); | |
| ByteArrayInputStream is = new ByteArrayInputStream(bytes); | |
| ObjectInputStream ois = new ObjectInputStream(is); | |
| File newFile = (File) ois.readObject(); | |
| // test | |
| String newPath = newFile.getPath(); | |
| if (!path.equals(newPath)) { | |
| throw new RuntimeException( | |
| "Serialization should not change file path"); | |
| } | |
| test(newFile, false); | |
| } catch (IOException | ClassNotFoundException ex) { | |
| System.err.println("Exception happens in testSerialization"); | |
| System.err.println(ex.getMessage()); | |
| } | |
| } | |
| private static void testTempFile() { | |
| final String[] names = {"x", "xx", "xxx", "xxxx"}; | |
| final String shortPrefix = "sp"; | |
| final String prefix = "prefix"; | |
| final String suffix = "suffix"; | |
| File tmpDir = new File("tmpDir"); | |
| for (String name : names) { | |
| int length = name.length(); | |
| for (int i = 0; i <= length; i++) { | |
| StringBuilder sbName = new StringBuilder(name); | |
| sbName.insert(i, CHAR_NUL); | |
| String curName = sbName.toString(); | |
| // test prefix | |
| testCreateTempFile(curName, suffix, tmpDir); | |
| // test suffix | |
| testCreateTempFile(shortPrefix, curName, tmpDir); | |
| testCreateTempFile(prefix, curName, tmpDir); | |
| // test directory | |
| testCreateTempFile(shortPrefix, suffix, new File(curName)); | |
| testCreateTempFile(prefix, suffix, new File(curName)); | |
| } | |
| } | |
| } | |
| private static void testCreateTempFile(String prefix, String suffix, | |
| File directory) { | |
| // createTempFile(String prefix, String suffix, File directory) | |
| boolean exceptionThrown = false; | |
| boolean shortPrefix = (prefix.length() < 3); | |
| if (shortPrefix) { | |
| try { | |
| File.createTempFile(prefix, suffix, directory); | |
| } catch (IllegalArgumentException ex) { | |
| String actual = ex.getMessage(); | |
| String expected = "Prefix string \"" + prefix + | |
| "\" too short: length must be at least 3"; | |
| if (actual != null && actual.equals(expected)) | |
| exceptionThrown = true; | |
| } catch (IOException ioe) { | |
| System.err.println("IOException happens in testCreateTempFile"); | |
| System.err.println(ioe.getMessage()); | |
| } | |
| } else { | |
| try { | |
| File.createTempFile(prefix, suffix, directory); | |
| } catch (IOException ex) { | |
| String err = "Unable to create temporary file"; | |
| if (ex.getMessage() != null && ex.getMessage().startsWith(err)) | |
| exceptionThrown = true; | |
| else { | |
| throw new RuntimeException("Get IOException with message, " | |
| + ex.getMessage() + ", expect message, "+ err); | |
| } | |
| } | |
| } | |
| if (!exceptionThrown) { | |
| throw new RuntimeException("createTempFile() should throw" | |
| + (shortPrefix ? " IllegalArgumentException" | |
| : " IOException")); | |
| } | |
| } | |
| } |