8061777: (zipfs) IllegalArgumentException in ZipCoder.toString when using Shitft_JIS

Reviewed-by: psandoz
This commit is contained in:
Xueming Shen 2016-06-01 09:52:08 -07:00
parent 78bb28e4af
commit d17f9b96fe
3 changed files with 96 additions and 8 deletions
jdk
src/jdk.zipfs/share/classes/jdk/nio/zipfs
test/jdk/nio/zipfs

@ -69,7 +69,7 @@ class ZipFileSystem extends FileSystem {
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 @@ class ZipFileSystem extends FileSystem {
@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 @@ class ZipFileSystem extends FileSystem {
sb.append(path);
}
}
return new ZipPath(this, getBytes(sb.toString()));
return new ZipPath(this, sb.toString());
}
@Override

@ -52,13 +52,28 @@ final class ZipPath implements Path {
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 @@ final class ZipPath implements Path {
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++) {

@ -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 class ZFSTests {
public static void main(String[] args) throws Throwable {
test7156873();
test8061777();
tests();
}
@ -62,6 +63,34 @@ public class ZFSTests {
}
}
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 {