java-topology/test/jdk/build/CheckFiles.java
russell@unturf.com 0a580b313d 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.
2026-03-26 17:11:57 -04:00

244 lines
10 KiB
Java

/*
* Copyright (c) 2026 SAP SE. All rights reserved.
* Copyright (c) 2026, 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.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import jdk.test.lib.Platform;
/*
* @test
* @summary Check for unwanted files (types/extensions) in the jdk image
* @library /test/lib
* @requires !vm.debug
* @run main CheckFiles
*/
public class CheckFiles {
// Set this property on command line to scan an alternate dir or file:
// JTREG=JAVA_OPTIONS=-Djdk.test.build.CheckFiles.dir=/path/to/dir
public static final String DIR_PROPERTY = "jdk.test.build.CheckFiles.dir";
private static boolean isGpl(Path myFile) {
if (myFile == null || !Files.exists(myFile)) {
return false;
}
try {
String firstLine = Files.readAllLines(myFile).stream()
.findFirst().orElse("");
return firstLine.contains("The GNU General Public License (GPL)");
} catch (IOException e) {
return false;
}
}
public static void main(String[] args) throws Exception {
String jdkPathString = System.getProperty("test.jdk");
Path jdkHome = Paths.get(jdkPathString);
Path mainDirToScan = jdkHome;
String overrideDir = System.getProperty(DIR_PROPERTY);
if (overrideDir != null) {
mainDirToScan = Paths.get(overrideDir);
}
System.out.println("Main directory to scan:" + mainDirToScan);
Path binDir = mainDirToScan.resolve("bin");
Path libDir = mainDirToScan.resolve("lib");
Path includeDir = mainDirToScan.resolve("include");
Path jmodsDir = mainDirToScan.resolve("jmods");
System.out.println("Bin directory to scan:" + binDir);
ArrayList<String> allowedEndingsBinDir = new ArrayList<>();
// UNIX - no extensions are allowed; Windows : .dll, .exe, .pdb, .jsa
if (Platform.isWindows()) {
allowedEndingsBinDir.add(".dll");
allowedEndingsBinDir.add(".exe");
allowedEndingsBinDir.add(".pdb");
allowedEndingsBinDir.add(".jsa");
}
boolean binDirRes = scanFiles(binDir, allowedEndingsBinDir);
System.out.println("Lib directory to scan:" + libDir);
ArrayList<String> allowedEndingsLibDir = new ArrayList<>();
allowedEndingsLibDir.add(".jfc"); // jfr config files
allowedEndingsLibDir.add("cacerts");
allowedEndingsLibDir.add("blocked.certs");
allowedEndingsLibDir.add("public_suffix_list.dat");
allowedEndingsLibDir.add("classlist");
allowedEndingsLibDir.add("fontconfig.bfc");
allowedEndingsLibDir.add("fontconfig.properties.src");
allowedEndingsLibDir.add("ct.sym");
allowedEndingsLibDir.add("jrt-fs.jar");
allowedEndingsLibDir.add("jvm.cfg");
allowedEndingsLibDir.add("modules");
allowedEndingsLibDir.add("psfontj2d.properties");
allowedEndingsLibDir.add("psfont.properties.ja");
allowedEndingsLibDir.add("src.zip");
allowedEndingsLibDir.add("tzdb.dat");
allowedEndingsLibDir.add("javafx-swt.jar");
allowedEndingsLibDir.add("javafx.properties");
if (Platform.isWindows()) {
allowedEndingsLibDir.add(".lib");
allowedEndingsLibDir.add("tzmappings");
} else {
allowedEndingsLibDir.add("jexec");
allowedEndingsLibDir.add("jspawnhelper");
allowedEndingsLibDir.add(".jsa");
if (Platform.isOSX()) {
allowedEndingsLibDir.add("shaders.metallib");
allowedEndingsLibDir.add(".dylib");
} else {
allowedEndingsLibDir.add(".so");
}
if (Platform.isAix()) {
allowedEndingsLibDir.add("tzmappings");
}
}
boolean libDirRes = scanFiles(libDir, allowedEndingsLibDir);
if (binDirRes) {
System.out.println("Bin directory scan successful.");
} else {
throw new Error("bin dir scan failed");
}
if (libDirRes) {
System.out.println("Lib directory scan successful.");
} else {
throw new Error("lib dir scan failed");
}
if (Files.isDirectory(includeDir)) {
System.out.println("Include directory to scan:" + includeDir);
ArrayList<String> allowedEndingsIncludeDir = new ArrayList<>();
allowedEndingsIncludeDir.add(".h");
allowedEndingsIncludeDir.add(".hpp");
boolean includeDirRes = scanFiles(includeDir, allowedEndingsIncludeDir);
if (includeDirRes) {
System.out.println("Include directory scan successful.");
} else {
throw new Error("include dir scan failed");
}
}
// when enabling "JEP 493: Linking Run-Time Images without JMODs" we do not
// have the jmods folder at all, so first test the presence of the folder
if (Files.isDirectory(jmodsDir)) {
System.out.println("Jmods directory to scan:" + jmodsDir);
ArrayList<String> allowedEndingsJmodsDir = new ArrayList<>();
allowedEndingsJmodsDir.add(".jmod");
boolean jmodsDirRes = scanFiles(jmodsDir, allowedEndingsJmodsDir);
if (jmodsDirRes) {
System.out.println("Jmods directory scan successful.");
} else {
throw new Error("jmods dir scan failed");
}
}
Path legalDir = mainDirToScan.resolve("legal");
Path javabaseLicenseFile = mainDirToScan.resolve("legal/java.base/LICENSE");
if (isGpl(javabaseLicenseFile)) { // for now check only legal dir of GPL based images; other ones might have other content
System.out.println("GPL info found in java.base LICENSE file");
ArrayList<String> allowedEndingsLegalDir = new ArrayList<>();
allowedEndingsLegalDir.add(".md");
allowedEndingsLegalDir.add("ADDITIONAL_LICENSE_INFO");
allowedEndingsLegalDir.add("ASSEMBLY_EXCEPTION");
allowedEndingsLegalDir.add("LICENSE");
ArrayList<String> requiredFilesInLegalSubdirs = new ArrayList<>();
requiredFilesInLegalSubdirs.add("LICENSE");
requiredFilesInLegalSubdirs.add("ADDITIONAL_LICENSE_INFO");
requiredFilesInLegalSubdirs.add("ASSEMBLY_EXCEPTION");
System.out.println("Legal directory to scan:" + legalDir);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(legalDir)) {
for (Path subfolder : stream) {
if (Files.isDirectory(subfolder)) {
System.out.println("Checking legal dir subfolder for required files: " + subfolder.getFileName());
for (String fileName : requiredFilesInLegalSubdirs) {
Path filePath = subfolder.resolve(fileName);
if (Files.exists(filePath)) {
System.out.println(" Found " + fileName);
} else {
System.out.println(" Missing " + fileName);
throw new Error("legal dir scan for required files failed");
}
}
}
}
}
boolean legalDirRes = scanFiles(legalDir, allowedEndingsLegalDir);
if (legalDirRes) {
System.out.println("Legal directory scan successful.");
} else {
throw new Error("Legal dir scan failed");
}
}
}
private static boolean scanFiles(Path root, ArrayList<String> allowedEndings) throws IOException {
AtomicBoolean badFileFound = new AtomicBoolean(false);
Files.walkFileTree(root, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fullFileName = file.toString();
String fileName = file.getFileName().toString();
System.out.println(" visiting file:" + fullFileName);
checkFile(fileName, allowedEndings);
return super.visitFile(file, attrs);
}
private void checkFile(String name, ArrayList<String> allowedEndings) {
if (allowedEndings.isEmpty()) { // no file extensions allowed
int lastDot = name.lastIndexOf('.');
if (lastDot > 0) {
System.out.println(" --> ERROR this file is not allowed:" + name);
badFileFound.set(true);
}
} else {
boolean allowed = allowedEndings.stream().anyMatch(name::endsWith);
if (! allowed) {
System.out.println(" --> ERROR this file is not allowed:" + name);
badFileFound.set(true);
}
}
}
});
return !badFileFound.get();
}
}