changeset 14952:cb08a9788178

8061777: (zipfs) IllegalArgumentException in ZipCoder.toString when using Shitft_JIS Reviewed-by: andrew
author sgehwolf
date Mon, 22 Feb 2021 06:07:01 +0000
parents 97302801cfa2
children 20e00dd20a92
files src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java test/demo/zipfs/ZFSTests.java
diffstat 3 files changed, 95 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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)
--- 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<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 testOpenOptions() throws Throwable {
         Path path = Paths.get("file.zip");
         try {