1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 8003992 26 * @summary Test a file whose path name is embedded with NUL character, and 27 * ensure it is handled correctly. 28 * @author Dan Xu 29 */ 30 31 import java.io.File; 32 import java.io.FileFilter; 33 import java.io.FileInputStream; 34 import java.io.FileOutputStream; 35 import java.io.RandomAccessFile; 36 import java.io.FileNotFoundException; 37 import java.io.FilenameFilter; 38 import java.io.IOException; 39 import java.net.MalformedURLException; 40 import java.nio.file.InvalidPathException; 41 import java.io.ByteArrayInputStream; 42 import java.io.ByteArrayOutputStream; 43 import java.io.ObjectOutputStream; 44 import java.io.ObjectInputStream; 45 46 public class NulFile { 47 48 private static final char CHAR_NUL = '\u0000'; 49 50 private static final String ExceptionMsg = "Invalid file path"; 51 52 public static void main(String[] args) { 53 testFile(); 54 testFileInUnix(); 55 testFileInWindows(); 56 testTempFile(); 57 } 58 59 private static void testFile() { 60 test(new File(new StringBuilder().append(CHAR_NUL).toString())); 61 test(new File( 62 new StringBuilder().append("").append(CHAR_NUL).toString())); 63 test(new File( 64 new StringBuilder().append(CHAR_NUL).append("").toString())); 65 } 66 67 private static void testFileInUnix() { 68 String osName = System.getProperty("os.name"); 69 if (osName.startsWith("Windows")) 70 return; 71 72 String unixFile = "/"; 73 test(unixFile); 74 75 unixFile = "//"; 76 test(unixFile); 77 78 unixFile = "data/info"; 79 test(unixFile); 80 81 unixFile = "/data/info"; 82 test(unixFile); 83 84 unixFile = "//data//info"; 85 test(unixFile); 86 } 87 88 private static void testFileInWindows() { 89 String osName = System.getProperty("os.name"); 90 if (!osName.startsWith("Windows")) 91 return; 92 93 String windowsFile = "\\"; 94 test(windowsFile); 95 96 windowsFile = "\\\\"; 97 test(windowsFile); 98 99 windowsFile = "/"; 100 test(windowsFile); 101 102 windowsFile = "//"; 103 test(windowsFile); 104 105 windowsFile = "/\\"; 106 test(windowsFile); 107 108 windowsFile = "\\/"; 109 test(windowsFile); 110 111 windowsFile = "data\\info"; 112 test(windowsFile); 113 114 windowsFile = "\\data\\info"; 115 test(windowsFile); 116 117 windowsFile = "\\\\server\\data\\info"; 118 test(windowsFile); 119 120 windowsFile = "z:data\\info"; 121 test(windowsFile); 122 123 windowsFile = "z:\\data\\info"; 124 test(windowsFile); 125 } 126 127 private static void test(final String name) { 128 int length = name.length(); 129 130 for (int i = 0; i <= length; i++) { 131 StringBuilder sbName = new StringBuilder(name); 132 sbName.insert(i, CHAR_NUL); 133 String curName = sbName.toString(); 134 135 // test File(String parent, String child) 136 File testFile = new File(curName, "child"); 137 test(testFile); 138 testFile = new File("parent", curName); 139 test(testFile); 140 141 // test File(String pathname) 142 testFile = new File(curName); 143 test(testFile); 144 145 // test File(File parent, String child) 146 testFile = new File(new File(curName), "child"); 147 test(testFile); 148 testFile = new File(new File("parent"), curName); 149 test(testFile); 150 151 // test FileInputStream 152 testFileInputStream(curName); 153 154 // test FileOutputStream 155 testFileOutputStream(curName); 156 157 // test RandomAccessFile 158 testRandomAccessFile(curName); 159 } 160 } 161 162 private static void testFileInputStream(final String str) { 163 boolean exceptionThrown = false; 164 FileInputStream is = null; 165 try { 166 is = new FileInputStream(str); 167 } catch (FileNotFoundException ex) { 168 if (ExceptionMsg.equals(ex.getMessage())) 169 exceptionThrown = true; 170 } 171 if (!exceptionThrown) { 172 throw new RuntimeException("FileInputStream constructor" 173 + " should throw FileNotFoundException"); 174 } 175 if (is != null) { 176 throw new RuntimeException("FileInputStream constructor" 177 + " should fail"); 178 } 179 180 exceptionThrown = false; 181 is = null; 182 try { 183 is = new FileInputStream(new File(str)); 184 } catch (FileNotFoundException ex) { 185 if (ExceptionMsg.equals(ex.getMessage())) 186 exceptionThrown = true; 187 } 188 if (!exceptionThrown) { 189 throw new RuntimeException("FileInputStream constructor" 190 + " should throw FileNotFoundException"); 191 } 192 if (is != null) { 193 throw new RuntimeException("FileInputStream constructor" 194 + " should fail"); 195 } 196 } 197 198 private static void testFileOutputStream(final String str) { 199 boolean exceptionThrown = false; 200 FileOutputStream os = null; 201 try { 202 os = new FileOutputStream(str); 203 } catch (FileNotFoundException ex) { 204 if (ExceptionMsg.equals(ex.getMessage())) 205 exceptionThrown = true; 206 } 207 if (!exceptionThrown) { 208 throw new RuntimeException("FileOutputStream constructor" 209 + " should throw FileNotFoundException"); 210 } 211 if (os != null) { 212 throw new RuntimeException("FileOutputStream constructor" 213 + " should fail"); 214 } 215 216 exceptionThrown = false; 217 os = null; 218 try { 219 os = new FileOutputStream(new File(str)); 220 } catch (FileNotFoundException ex) { 221 if (ExceptionMsg.equals(ex.getMessage())) 222 exceptionThrown = true; 223 } 224 if (!exceptionThrown) { 225 throw new RuntimeException("FileOutputStream constructor" 226 + " should throw FileNotFoundException"); 227 } 228 if (os != null) { 229 throw new RuntimeException("FileOutputStream constructor" 230 + " should fail"); 231 } 232 } 233 234 private static void testRandomAccessFile(final String str) { 235 boolean exceptionThrown = false; 236 RandomAccessFile raf = null; 237 String[] modes = {"r", "rw", "rws", "rwd"}; 238 239 for (String mode : modes) { 240 try { 241 raf = new RandomAccessFile(str, mode); 242 } catch (FileNotFoundException ex) { 243 if (ExceptionMsg.equals(ex.getMessage())) 244 exceptionThrown = true; 245 } 246 if (!exceptionThrown) { 247 throw new RuntimeException("RandomAccessFile constructor" 248 + " should throw FileNotFoundException"); 249 } 250 if (raf != null) { 251 throw new RuntimeException("RandomAccessFile constructor" 252 + " should fail"); 253 } 254 255 exceptionThrown = false; 256 raf = null; 257 try { 258 raf = new RandomAccessFile(new File(str), mode); 259 } catch (FileNotFoundException ex) { 260 if (ExceptionMsg.equals(ex.getMessage())) 261 exceptionThrown = true; 262 } 263 if (!exceptionThrown) { 264 throw new RuntimeException("RandomAccessFile constructor" 265 + " should throw FileNotFoundException"); 266 } 267 if (raf != null) { 268 throw new RuntimeException("RandomAccessFile constructor" 269 + " should fail"); 270 } 271 } 272 } 273 274 private static void test(File testFile) { 275 test(testFile, false); 276 // test serialization 277 testSerialization(testFile); 278 } 279 280 @SuppressWarnings("deprecation") 281 private static void test(File testFile, boolean derived) { 282 boolean exceptionThrown = false; 283 284 if (testFile == null) { 285 throw new RuntimeException("test file should not be null."); 286 } 287 288 // getPath() 289 if (testFile.getPath().indexOf(CHAR_NUL) < 0) { 290 throw new RuntimeException( 291 "File path should contain Nul character"); 292 } 293 // getAbsolutePath() 294 if (testFile.getAbsolutePath().indexOf(CHAR_NUL) < 0) { 295 throw new RuntimeException( 296 "File absolute path should contain Nul character"); 297 } 298 // getAbsoluteFile() 299 File derivedAbsFile = testFile.getAbsoluteFile(); 300 if (derived) { 301 if (derivedAbsFile.getPath().indexOf(CHAR_NUL) < 0) { 302 throw new RuntimeException( 303 "Derived file path should also contain Nul character"); 304 } 305 } else { 306 test(derivedAbsFile, true); 307 } 308 // getCanonicalPath() 309 try { 310 exceptionThrown = false; 311 testFile.getCanonicalPath(); 312 } catch (IOException ex) { 313 if (ExceptionMsg.equals(ex.getMessage())) 314 exceptionThrown = true; 315 } 316 if (!exceptionThrown) { 317 throw new RuntimeException( 318 "getCanonicalPath() should throw IOException with" 319 + " message \"" + ExceptionMsg + "\""); 320 } 321 // getCanonicalFile() 322 try { 323 exceptionThrown = false; 324 testFile.getCanonicalFile(); 325 } catch (IOException ex) { 326 if (ExceptionMsg.equals(ex.getMessage())) 327 exceptionThrown = true; 328 } 329 if (!exceptionThrown) { 330 throw new RuntimeException( 331 "getCanonicalFile() should throw IOException with" 332 + " message \"" + ExceptionMsg + "\""); 333 } 334 // toURL() 335 try { 336 exceptionThrown = false; 337 testFile.toURL(); 338 } catch (MalformedURLException ex) { 339 if (ExceptionMsg.equals(ex.getMessage())) 340 exceptionThrown = true; 341 } 342 if (!exceptionThrown) { 343 throw new RuntimeException("toURL() should throw IOException with" 344 + " message \"" + ExceptionMsg + "\""); 345 } 346 // canRead() 347 if (testFile.canRead()) 348 throw new RuntimeException("File should not be readable"); 349 // canWrite() 350 if (testFile.canWrite()) 351 throw new RuntimeException("File should not be writable"); 352 // exists() 353 if (testFile.exists()) 354 throw new RuntimeException("File should not be existed"); 355 // isDirectory() 356 if (testFile.isDirectory()) 357 throw new RuntimeException("File should not be a directory"); 358 // isFile() 359 if (testFile.isFile()) 360 throw new RuntimeException("File should not be a file"); 361 // isHidden() 362 if (testFile.isHidden()) 363 throw new RuntimeException("File should not be hidden"); 364 // lastModified() 365 if (testFile.lastModified() != 0L) 366 throw new RuntimeException("File last modified time should be 0L"); 367 // length() 368 if (testFile.length() != 0L) 369 throw new RuntimeException("File length should be 0L"); 370 // createNewFile() 371 try { 372 exceptionThrown = false; 373 testFile.createNewFile(); 374 } catch (IOException ex) { 375 if (ExceptionMsg.equals(ex.getMessage())) 376 exceptionThrown = true; 377 } 378 if (!exceptionThrown) { 379 throw new RuntimeException( 380 "createNewFile() should throw IOException with" 381 + " message \"" + ExceptionMsg + "\""); 382 } 383 // delete() 384 if (testFile.delete()) 385 throw new RuntimeException("Delete operation should fail"); 386 // list() 387 if (testFile.list() != null) 388 throw new RuntimeException("File list() should return null"); 389 // list(FilenameFilter) 390 FilenameFilter fnFilter = new FilenameFilter() { 391 @Override 392 public boolean accept(File dir, String name) { 393 return false; 394 } 395 }; 396 if (testFile.list(fnFilter) != null) { 397 throw new RuntimeException("File list(FilenameFilter) should" 398 + " return null"); 399 } 400 // listFiles() 401 if (testFile.listFiles() != null) 402 throw new RuntimeException("File listFiles() should return null"); 403 // listFiles(FilenameFilter) 404 if (testFile.listFiles(fnFilter) != null) { 405 throw new RuntimeException("File listFiles(FilenameFilter)" 406 + " should return null"); 407 } 408 // listFiles(FileFilter) 409 FileFilter fFilter = new FileFilter() { 410 @Override 411 public boolean accept(File file) { 412 return false; 413 } 414 }; 415 if (testFile.listFiles(fFilter) != null) { 416 throw new RuntimeException("File listFiles(FileFilter)" 417 + " should return null"); 418 } 419 // mkdir() 420 if (testFile.mkdir()) { 421 throw new RuntimeException("File should not be able to" 422 + " create directory"); 423 } 424 // mkdirs() 425 if (testFile.mkdirs()) { 426 throw new RuntimeException("File should not be able to" 427 + " create directories"); 428 } 429 // renameTo(File) 430 if (testFile.renameTo(new File("dest"))) 431 throw new RuntimeException("File rename should fail"); 432 if (new File("dest").renameTo(testFile)) 433 throw new RuntimeException("File rename should fail"); 434 try { 435 exceptionThrown = false; 436 testFile.renameTo(null); 437 } catch (NullPointerException ex) { 438 exceptionThrown = true; 439 } 440 if (!exceptionThrown) { 441 throw new RuntimeException("File rename should thrown NPE"); 442 } 443 // setLastModified(long) 444 if (testFile.setLastModified(0L)) { 445 throw new RuntimeException("File should fail to set" 446 + " last modified time"); 447 } 448 try { 449 exceptionThrown = false; 450 testFile.setLastModified(-1); 451 } catch (IllegalArgumentException ex) { 452 if ("Negative time".equals(ex.getMessage())) 453 exceptionThrown = true; 454 } 455 if (!exceptionThrown) { 456 throw new RuntimeException("File should fail to set" 457 + " last modified time with message \"Negative time\""); 458 } 459 // setReadOnly() 460 if (testFile.setReadOnly()) 461 throw new RuntimeException("File should fail to set read-only"); 462 // setWritable(boolean writable, boolean ownerOnly) 463 if (testFile.setWritable(true, true)) 464 throw new RuntimeException("File should fail to set writable"); 465 if (testFile.setWritable(true, false)) 466 throw new RuntimeException("File should fail to set writable"); 467 if (testFile.setWritable(false, true)) 468 throw new RuntimeException("File should fail to set writable"); 469 if (testFile.setWritable(false, false)) 470 throw new RuntimeException("File should fail to set writable"); 471 // setWritable(boolean writable) 472 if (testFile.setWritable(false)) 473 throw new RuntimeException("File should fail to set writable"); 474 if (testFile.setWritable(true)) 475 throw new RuntimeException("File should fail to set writable"); 476 // setReadable(boolean readable, boolean ownerOnly) 477 if (testFile.setReadable(true, true)) 478 throw new RuntimeException("File should fail to set readable"); 479 if (testFile.setReadable(true, false)) 480 throw new RuntimeException("File should fail to set readable"); 481 if (testFile.setReadable(false, true)) 482 throw new RuntimeException("File should fail to set readable"); 483 if (testFile.setReadable(false, false)) 484 throw new RuntimeException("File should fail to set readable"); 485 // setReadable(boolean readable) 486 if (testFile.setReadable(false)) 487 throw new RuntimeException("File should fail to set readable"); 488 if (testFile.setReadable(true)) 489 throw new RuntimeException("File should fail to set readable"); 490 // setExecutable(boolean executable, boolean ownerOnly) 491 if (testFile.setExecutable(true, true)) 492 throw new RuntimeException("File should fail to set executable"); 493 if (testFile.setExecutable(true, false)) 494 throw new RuntimeException("File should fail to set executable"); 495 if (testFile.setExecutable(false, true)) 496 throw new RuntimeException("File should fail to set executable"); 497 if (testFile.setExecutable(false, false)) 498 throw new RuntimeException("File should fail to set executable"); 499 // setExecutable(boolean executable) 500 if (testFile.setExecutable(false)) 501 throw new RuntimeException("File should fail to set executable"); 502 if (testFile.setExecutable(true)) 503 throw new RuntimeException("File should fail to set executable"); 504 // canExecute() 505 if (testFile.canExecute()) 506 throw new RuntimeException("File should not be executable"); 507 // getTotalSpace() 508 if (testFile.getTotalSpace() != 0L) 509 throw new RuntimeException("The total space should be 0L"); 510 // getFreeSpace() 511 if (testFile.getFreeSpace() != 0L) 512 throw new RuntimeException("The free space should be 0L"); 513 // getUsableSpace() 514 if (testFile.getUsableSpace() != 0L) 515 throw new RuntimeException("The usable space should be 0L"); 516 // compareTo(File null) 517 try { 518 exceptionThrown = false; 519 testFile.compareTo(null); 520 } catch (NullPointerException ex) { 521 exceptionThrown = true; 522 } 523 if (!exceptionThrown) { 524 throw new RuntimeException("compareTo(null) should throw NPE"); 525 } 526 // toString() 527 if (testFile.toString().indexOf(CHAR_NUL) < 0) { 528 throw new RuntimeException( 529 "File path should contain Nul character"); 530 } 531 // toPath() 532 try { 533 exceptionThrown = false; 534 testFile.toPath(); 535 } catch (InvalidPathException ex) { 536 exceptionThrown = true; 537 } 538 if (!exceptionThrown) { 539 throw new RuntimeException("toPath() should throw" 540 + " InvalidPathException"); 541 } 542 } 543 544 private static void testSerialization(File testFile) { 545 String path = testFile.getPath(); 546 try { 547 // serialize test file 548 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 549 ObjectOutputStream oos = new ObjectOutputStream(baos); 550 oos.writeObject(testFile); 551 oos.close(); 552 // deserialize test file 553 byte[] bytes = baos.toByteArray(); 554 ByteArrayInputStream is = new ByteArrayInputStream(bytes); 555 ObjectInputStream ois = new ObjectInputStream(is); 556 File newFile = (File) ois.readObject(); 557 // test 558 String newPath = newFile.getPath(); 559 if (!path.equals(newPath)) { 560 throw new RuntimeException( 561 "Serialization should not change file path"); 562 } 563 test(newFile, false); 564 } catch (IOException | ClassNotFoundException ex) { 565 System.err.println("Exception happens in testSerialization"); 566 System.err.println(ex.getMessage()); 567 } 568 } 569 570 private static void testTempFile() { 571 final String[] names = {"x", "xx", "xxx", "xxxx"}; 572 final String shortPrefix = "sp"; 573 final String prefix = "prefix"; 574 final String suffix = "suffix"; 575 File tmpDir = new File("tmpDir"); 576 577 for (String name : names) { 578 int length = name.length(); 579 for (int i = 0; i <= length; i++) { 580 StringBuilder sbName = new StringBuilder(name); 581 sbName.insert(i, CHAR_NUL); 582 String curName = sbName.toString(); 583 584 // test prefix 585 testCreateTempFile(curName, suffix, tmpDir); 586 // test suffix 587 testCreateTempFile(shortPrefix, curName, tmpDir); 588 testCreateTempFile(prefix, curName, tmpDir); 589 // test directory 590 testCreateTempFile(shortPrefix, suffix, new File(curName)); 591 testCreateTempFile(prefix, suffix, new File(curName)); 592 } 593 } 594 } 595 596 private static void testCreateTempFile(String prefix, String suffix, 597 File directory) { 598 // createTempFile(String prefix, String suffix, File directory) 599 boolean exceptionThrown = false; 600 boolean shortPrefix = (prefix.length() < 3); 601 if (shortPrefix) { 602 try { 603 File.createTempFile(prefix, suffix, directory); 604 } catch (IllegalArgumentException ex) { 605 if ("Prefix string too short".equals(ex.getMessage())) 606 exceptionThrown = true; 607 } catch (IOException ioe) { 608 System.err.println("IOException happens in testCreateTempFile"); 609 System.err.println(ioe.getMessage()); 610 } 611 } else { 612 try { 613 File.createTempFile(prefix, suffix, directory); 614 } catch (IOException ex) { 615 if (ExceptionMsg.equals(ex.getMessage())) 616 exceptionThrown = true; 617 } 618 } 619 if (!exceptionThrown) { 620 throw new RuntimeException("createTempFile() should throw" 621 + (shortPrefix ? " IllegalArgumentException" 622 : " IOException")); 623 } 624 } 625 }