undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
137
test/jdk/java/util/zip/ZipFile/ZipFileSharedSourceTest.java
Normal file
137
test/jdk/java/util/zip/ZipFile/ZipFileSharedSourceTest.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8347712
|
||||
* @summary verify that different instances of java.util.zip.ZipFile do not share
|
||||
* the same instance of (non-thread-safe) java.nio.charset.CharsetEncoder/CharsetDecoder
|
||||
* @run junit ZipFileSharedSourceTest
|
||||
*/
|
||||
public class ZipFileSharedSourceTest {
|
||||
|
||||
static Path createZipFile(final Charset charset) throws Exception {
|
||||
final Path zipFilePath = Files.createTempFile(Path.of("."), "8347712", ".zip");
|
||||
try (OutputStream os = Files.newOutputStream(zipFilePath);
|
||||
ZipOutputStream zos = new ZipOutputStream(os, charset)) {
|
||||
final int numEntries = 10240;
|
||||
for (int i = 1; i <= numEntries; i++) {
|
||||
final ZipEntry entry = new ZipEntry("entry-" + i);
|
||||
zos.putNextEntry(entry);
|
||||
zos.write("foo bar".getBytes(US_ASCII));
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
return zipFilePath;
|
||||
}
|
||||
|
||||
static List<Arguments> charsets() {
|
||||
return List.of(
|
||||
Arguments.of(StandardCharsets.UTF_8),
|
||||
Arguments.of(StandardCharsets.ISO_8859_1),
|
||||
Arguments.of(US_ASCII)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* In this test, multiple concurrent threads each create an instance of java.util.zip.ZipFile
|
||||
* with the given {@code charset} for the same underlying ZIP file. Each of the threads
|
||||
* then iterate over the entries of their ZipFile instance. The test verifies that such access,
|
||||
* where each thread is accessing an independent ZipFile instance corresponding to the same
|
||||
* underlying ZIP file, doesn't lead to unexpected failures contributed by concurrent
|
||||
* threads.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("charsets")
|
||||
void testMultipleZipFileInstances(final Charset charset) throws Exception {
|
||||
final Path zipFilePath = createZipFile(charset);
|
||||
final int numTasks = 200;
|
||||
final CountDownLatch startLatch = new CountDownLatch(numTasks);
|
||||
final List<Future<Void>> results = new ArrayList<>();
|
||||
try (final ExecutorService executor =
|
||||
Executors.newThreadPerTaskExecutor(Thread.ofPlatform().factory())) {
|
||||
for (int i = 0; i < numTasks; i++) {
|
||||
final var task = new ZipEntryIteratingTask(zipFilePath, charset,
|
||||
startLatch);
|
||||
results.add(executor.submit(task));
|
||||
}
|
||||
System.out.println(numTasks + " tasks submitted, waiting for them to complete");
|
||||
for (final Future<Void> f : results) {
|
||||
f.get();
|
||||
}
|
||||
}
|
||||
System.out.println("All " + numTasks + " tasks completed successfully");
|
||||
}
|
||||
|
||||
private static final class ZipEntryIteratingTask implements Callable<Void> {
|
||||
private final Path file;
|
||||
private final Charset charset;
|
||||
private final CountDownLatch startLatch;
|
||||
|
||||
private ZipEntryIteratingTask(final Path file, final Charset charset,
|
||||
final CountDownLatch startLatch) {
|
||||
this.file = file;
|
||||
this.charset = charset;
|
||||
this.startLatch = startLatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
// let other tasks know we are ready to run
|
||||
this.startLatch.countDown();
|
||||
// wait for other tasks to be ready to run
|
||||
this.startLatch.await();
|
||||
// create a new instance of ZipFile and iterate over the entries
|
||||
try (final ZipFile zf = new ZipFile(this.file.toFile(), this.charset)) {
|
||||
final var entries = zf.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
final ZipEntry ze = entries.nextElement();
|
||||
// additionally exercise the ZipFile.getEntry() method
|
||||
zf.getEntry(ze.getName());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue