# HG changeset patch # User sgehwolf # Date 1613974021 0 # Node ID cb08a9788178afa0536d16c94fbd328b1a66f23c # Parent 97302801cfa2d633eb4ac35ac4af9af6fb408d93 8061777: (zipfs) IllegalArgumentException in ZipCoder.toString when using Shitft_JIS Reviewed-by: andrew diff -r 97302801cfa2 -r cb08a9788178 src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Tue May 26 22:10:37 2015 +0800 +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Mon Feb 22 06:07:01 2021 +0000 @@ -83,7 +83,7 @@ private final ZipPath defaultdir; private boolean readOnly = false; private final Path zfpath; - private final ZipCoder zc; + final ZipCoder zc; // configurable by env map private final String defaultDir; // default dir for the file system @@ -183,7 +183,7 @@ } path = sb.toString(); } - return new ZipPath(this, getBytes(path)); + return new ZipPath(this, path); } @Override diff -r 97302801cfa2 -r cb08a9788178 src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java --- a/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Tue May 26 22:10:37 2015 +0800 +++ b/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Mon Feb 22 06:07:01 2021 +0000 @@ -67,13 +67,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 @@ -478,6 +493,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() { if (path.length == 0) diff -r 97302801cfa2 -r cb08a9788178 test/demo/zipfs/ZFSTests.java --- a/test/demo/zipfs/ZFSTests.java Tue May 26 22:10:37 2015 +0800 +++ b/test/demo/zipfs/ZFSTests.java Mon Feb 22 06:07:01 2021 +0000 @@ -22,7 +22,7 @@ */ /* @test - @bug 7156873 8028480 8034773 + @bug 7156873 8028480 8034773 8061777 @summary ZipFileSystem regression tests */ @@ -38,6 +38,7 @@ public static void main(String[] args) throws Throwable { test7156873(); + test8061777(); testOpenOptions(); } @@ -57,6 +58,34 @@ } } + static void test8061777() throws Throwable { + Path path = Paths.get("file.zip"); + try { + URI uri = URI.create("jar:" + path.toUri()); + Map env = new HashMap(); + 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 testOpenOptions() throws Throwable { Path path = Paths.get("file.zip"); try {