8061777: (zipfs) IllegalArgumentException in ZipCoder.toString when using Shitft_JIS
Reviewed-by: psandoz
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jun 01 14:33:44 2016 +0100
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jun 01 09:52:08 2016 -0700
@@ -69,7 +69,7 @@
private final ZipFileSystemProvider provider;
private final Path zfpath;
- private final ZipCoder zc;
+ final ZipCoder zc;
private final boolean noExtt; // see readExtra()
private final ZipPath rootdir;
// configurable by env map
@@ -163,7 +163,7 @@
@Override
public ZipPath getPath(String first, String... more) {
if (more.length == 0) {
- return new ZipPath(this, getBytes(first));
+ return new ZipPath(this, first);
}
StringBuilder sb = new StringBuilder();
sb.append(first);
@@ -175,7 +175,7 @@
sb.append(path);
}
}
- return new ZipPath(this, getBytes(sb.toString()));
+ return new ZipPath(this, sb.toString());
}
@Override
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Wed Jun 01 14:33:44 2016 +0100
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Wed Jun 01 09:52:08 2016 -0700
@@ -52,13 +52,28 @@
this(zfs, path, false);
}
- ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized)
- {
+ ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized) {
this.zfs = zfs;
- if (normalized)
+ if (normalized) {
this.path = path;
- else
+ } else {
+ if (zfs.zc.isUTF8()) {
+ this.path = normalize(path);
+ } else {
+ // see normalize(String);
+ this.path = normalize(zfs.getString(path));
+ }
+ }
+ }
+
+ ZipPath(ZipFileSystem zfs, String path) {
+ this.zfs = zfs;
+ if (zfs.zc.isUTF8()) {
+ this.path = normalize(zfs.getBytes(path));
+ } else {
+ // see normalize(String);
this.path = normalize(path);
+ }
}
@Override
@@ -471,6 +486,50 @@
return (m == to.length)? to : Arrays.copyOf(to, m);
}
+ // if zfs is NOT in utf8, normalize the path as "String"
+ // to avoid incorrectly normalizing byte '0x5c' (as '\')
+ // to '/'.
+ private byte[] normalize(String path) {
+ int len = path.length();
+ if (len == 0)
+ return new byte[0];
+ char prevC = 0;
+ for (int i = 0; i < len; i++) {
+ char c = path.charAt(i);
+ if (c == '\\' || c == '\u0000')
+ return normalize(path, i, len);
+ if (c == '/' && prevC == '/')
+ return normalize(path, i - 1, len);
+ prevC = c;
+ }
+ if (len > 1 && prevC == '/')
+ path = path.substring(0, len - 1);
+ return zfs.getBytes(path);
+ }
+
+ private byte[] normalize(String path, int off, int len) {
+ StringBuilder to = new StringBuilder(len);
+ to.append(path, 0, off);
+ int m = off;
+ char prevC = 0;
+ while (off < len) {
+ char c = path.charAt(off++);
+ if (c == '\\')
+ c = '/';
+ if (c == '/' && prevC == '/')
+ continue;
+ if (c == '\u0000')
+ throw new InvalidPathException(path,
+ "Path: nul character not allowed");
+ to.append(c);
+ prevC = c;
+ }
+ len = to.length();
+ if (len > 1 && prevC == '/')
+ to.delete(len -1, len);
+ return zfs.getBytes(to.toString());
+ }
+
// Remove DotSlash(./) and resolve DotDot (..) components
private byte[] getResolved() {
for (int i = 0; i < path.length; i++) {
--- a/jdk/test/jdk/nio/zipfs/ZFSTests.java Wed Jun 01 14:33:44 2016 +0100
+++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java Wed Jun 01 09:52:08 2016 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 7156873 8040059 8028480 8034773 8153248
+ * @bug 7156873 8040059 8028480 8034773 8153248 8061777
* @summary ZipFileSystem regression tests
*
* @run main ZFSTests
@@ -43,6 +43,7 @@
public static void main(String[] args) throws Throwable {
test7156873();
+ test8061777();
tests();
}
@@ -62,6 +63,34 @@
}
}
+ static void test8061777() throws Throwable {
+ Path path = Paths.get("file.zip");
+ try {
+ URI uri = URI.create("jar:" + path.toUri());
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "true");
+ env.put("encoding", "Shift_JIS");
+ try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
+ FileSystemProvider fsp = fs.provider();
+ Path p = fs.getPath("/\u8868\u7533.txt"); // 0x95 0x5c 0x90 0x5c
+ try (OutputStream os = fsp.newOutputStream(p)) {
+ os.write("Hello!".getBytes("ASCII"));
+ }
+ Path dir = fs.getPath("/");
+ Files.list(dir)
+ .forEach( child -> {
+ System.out.println("child:" + child);
+ if (!child.toString().equals(p.toString()))
+ throw new RuntimeException("wrong path name created");
+ });
+ if (!"Hello!".equals(new String(Files.readAllBytes(p), "ASCII")))
+ throw new RuntimeException("wrong content in newly created file");
+ }
+ } finally {
+ Files.deleteIfExists(path);
+ }
+ }
+
static void tests() throws Throwable {
Path path = Paths.get("file.zip");
try {