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
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.SimpleFileServer;
|
||||
import static java.net.http.HttpClient.Builder.NO_PROXY;
|
||||
import static java.nio.file.StandardOpenOption.CREATE;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test idempotency and commutativity of responses with an exhaustive
|
||||
* set of binary request sequences
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.net.URIBuilder
|
||||
* @run junit/othervm IdempotencyAndCommutativityTest
|
||||
*/
|
||||
public class IdempotencyAndCommutativityTest {
|
||||
|
||||
static final Path CWD = Path.of(".").toAbsolutePath().normalize();
|
||||
static final InetSocketAddress LOOPBACK_ADDR = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
|
||||
|
||||
static final String FILE_NAME = "file.txt";
|
||||
static final String DIR_NAME = "";
|
||||
static final String MISSING_FILE_NAME = "doesNotExist";
|
||||
|
||||
static HttpServer server;
|
||||
static HttpClient client;
|
||||
|
||||
static final boolean ENABLE_LOGGING = true;
|
||||
static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver");
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws IOException {
|
||||
if (ENABLE_LOGGING) {
|
||||
ConsoleHandler ch = new ConsoleHandler();
|
||||
LOGGER.setLevel(Level.ALL);
|
||||
ch.setLevel(Level.ALL);
|
||||
LOGGER.addHandler(ch);
|
||||
}
|
||||
Path root = Files.createDirectories(CWD.resolve("testDirectory"));
|
||||
Files.writeString(root.resolve(FILE_NAME), "some text", CREATE);
|
||||
|
||||
client = HttpClient.newBuilder().proxy(NO_PROXY).build();
|
||||
server = SimpleFileServer.createFileServer(LOOPBACK_ADDR, root, SimpleFileServer.OutputLevel.VERBOSE);
|
||||
server.start();
|
||||
}
|
||||
|
||||
// Container of expected response state for a given request
|
||||
record ExchangeValues(String method, String resource, int respCode, String contentType) {}
|
||||
|
||||
// Creates an exhaustive set of binary exchange sequences
|
||||
public static Object[][] allBinarySequences() {
|
||||
final List<ExchangeValues> sequences = List.of(
|
||||
new ExchangeValues("GET", FILE_NAME, 200, "text/plain"),
|
||||
new ExchangeValues("GET", DIR_NAME, 200, "text/html; charset=UTF-8"),
|
||||
new ExchangeValues("GET", MISSING_FILE_NAME, 404, "text/html; charset=UTF-8"),
|
||||
new ExchangeValues("HEAD", FILE_NAME, 200, "text/plain"),
|
||||
new ExchangeValues("HEAD", DIR_NAME, 200, "text/html; charset=UTF-8"),
|
||||
new ExchangeValues("HEAD", MISSING_FILE_NAME, 404, "text/html; charset=UTF-8"),
|
||||
new ExchangeValues("UNKNOWN", FILE_NAME, 501, null),
|
||||
new ExchangeValues("UNKNOWN", DIR_NAME, 501, null),
|
||||
new ExchangeValues("UNKNOWN", MISSING_FILE_NAME, 501, null)
|
||||
);
|
||||
|
||||
return sequences.stream() // cartesian product
|
||||
.flatMap(s1 -> sequences.stream().map(s2 -> new ExchangeValues[] { s1, s2 }))
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("allBinarySequences")
|
||||
public void testBinarySequences(ExchangeValues e1, ExchangeValues e2) throws Exception {
|
||||
System.out.println("---");
|
||||
System.out.println(e1);
|
||||
executeExchange(e1);
|
||||
System.out.println(e2);
|
||||
executeExchange(e2);
|
||||
}
|
||||
|
||||
private static void executeExchange(ExchangeValues e) throws Exception {
|
||||
var request = HttpRequest.newBuilder(uri(server, e.resource()))
|
||||
.method(e.method(), HttpRequest.BodyPublishers.noBody())
|
||||
.build();
|
||||
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
assertEquals(e.respCode(), response.statusCode());
|
||||
if (e.contentType != null) {
|
||||
assertEquals(e.contentType(), response.headers().firstValue("content-type").get());
|
||||
} else {
|
||||
assertTrue(response.headers().firstValue("content-type").isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void teardown() {
|
||||
server.stop(0);
|
||||
}
|
||||
|
||||
static URI uri(HttpServer server, String path) {
|
||||
return URIBuilder.newBuilder()
|
||||
.host("localhost")
|
||||
.port(server.getAddress().getPort())
|
||||
.scheme("http")
|
||||
.path("/" + path)
|
||||
.buildUnchecked();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue