/* * 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")); } } }