8069211: (zipfs) ZipFileSystem creates corrupted zip if entry output stream gets closed more than once
Summary: to synchronize the write and close methods of the entry output stream
Reviewed-by: alanb
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Jan 22 12:33:05 2015 +0000
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Jan 22 08:51:45 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 201, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1533,6 +1533,7 @@
private CRC32 crc;
private Entry e;
private long written;
+ private boolean isClosed = false;
EntryOutputStream(Entry e, OutputStream os)
throws IOException
@@ -1545,9 +1546,14 @@
}
@Override
- public void write(byte b[], int off, int len) throws IOException {
+ public synchronized void write(byte b[], int off, int len)
+ throws IOException
+ {
if (e.type != Entry.FILECH) // only from sync
ensureOpen();
+ if (isClosed) {
+ throw new IOException("Stream closed");
+ }
if (off < 0 || len < 0 || off > b.length - len) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
@@ -1568,7 +1574,11 @@
}
@Override
- public void close() throws IOException {
+ public synchronized void close() throws IOException {
+ if (isClosed) {
+ return;
+ }
+ isClosed = true;
// TBD ensureOpen();
switch (e.method) {
case METHOD_DEFLATED:
--- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java Thu Jan 22 12:33:05 2015 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java Thu Jan 22 08:51:45 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -67,7 +68,7 @@
*
* @test
* @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
- * 7157656 8002390 7012868 7012856 8015728 8038500 8040059
+ * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211
* @summary Test Zip filesystem provider
* @run main ZipFSTester
* @run main/othervm/java.security.policy=test.policy ZipFSTester
@@ -89,6 +90,7 @@
test2(fs); // more tests
}
testTime(jarFile);
+ test8069211();
}
static void test0(FileSystem fs)
@@ -416,6 +418,29 @@
Files.delete(fsPath);
}
+ static void test8069211() throws Exception {
+ // create a new filesystem, copy this file into it
+ Map<String, Object> env = new HashMap<String, Object>();
+ env.put("create", "true");
+ Path fsPath = getTempPath();
+ try (FileSystem fs = newZipFileSystem(fsPath, env);) {
+ OutputStream out = Files.newOutputStream(fs.getPath("/foo"));
+ out.write("hello".getBytes());
+ out.close();
+ out.close();
+ }
+ try (FileSystem fs = newZipFileSystem(fsPath, new HashMap<String, Object>())) {
+ if (!Arrays.equals(Files.readAllBytes(fs.getPath("/foo")),
+ "hello".getBytes())) {
+ throw new RuntimeException("entry close() failed");
+ }
+ } catch (Exception x) {
+ throw new RuntimeException("entry close() failed", x);
+ } finally {
+ Files.delete(fsPath);
+ }
+ }
+
private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
throws Exception
{