--- /dev/null 2013-05-01 09:27:59.347801384 -0700 +++ new/test/java/io/File/NulFile.java 2013-05-01 17:25:04.198955616 -0700 @@ -0,0 +1,625 @@ +/* + * 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 + * @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) { + if ("Prefix string too short".equals(ex.getMessage())) + 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) { + if ("Unable to create temporary file".equals(ex.getMessage())) + exceptionThrown = true; + } + } + if (!exceptionThrown) { + throw new RuntimeException("createTempFile() should throw" + + (shortPrefix ? " IllegalArgumentException" + : " IOException")); + } + } +}