GT-3146: Preventing Ghidra from launching with 32-bit Java (fixes #882).

This commit is contained in:
Ryan Kurtz 2019-09-12 09:40:36 -04:00
parent d9da0f0b66
commit 0a3574d0c0
6 changed files with 93 additions and 37 deletions

View file

@ -224,10 +224,11 @@ public class LaunchSupport {
javaRange = min + "-" + max;
}
System.out.println("*******************************************************");
System.out.println("******************************************************************");
System.out.println(
javaName + " " + javaRange + " could not be found and must be manually chosen!");
System.out.println("*******************************************************");
javaName + " " + javaRange + " (" + javaConfig.getSupportedArchitecture() +
"-bit) could not be found and must be manually chosen!");
System.out.println("******************************************************************");
File javaHomeDir = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
@ -259,7 +260,7 @@ public class LaunchSupport {
}
System.out.println(
"Java version " + javaVersion + " is outside of supported range: [" +
javaRange + "]");
javaRange + " " + javaConfig.getSupportedArchitecture() + "-bit]");
}
catch (FileNotFoundException e) {
System.out.println(

View file

@ -84,6 +84,16 @@ public class JavaConfig {
return maxSupportedJava;
}
/**
* Gets the Java configuration's supported Java architecture. All supported Java
* configurations must have an architecture of <code>64</code>.
*
* @return The Java configuration's supported Java architecture (64).
*/
public int getSupportedArchitecture() {
return 64;
}
/**
* Gets the Java configuration's compiler compliance level that was used to build the
* associated installation.
@ -161,6 +171,10 @@ public class JavaConfig {
* @return True if the given Java version is supported by this Java launch configuration.
*/
public boolean isJavaVersionSupported(JavaVersion javaVersion) {
if (javaVersion.getArchitecture() != getSupportedArchitecture()) {
return false;
}
int major = javaVersion.getMajor();
return major >= minSupportedJava &&
(maxSupportedJava == 0 || major <= maxSupportedJava);
@ -229,29 +243,34 @@ public class JavaConfig {
*/
private JavaVersion runAndGetJavaVersion(File javaExecutable)
throws ParseException, IOException {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(new String[] { javaExecutable.getAbsolutePath(), "-version" });
String version = "";
String arch = "";
Process proc = Runtime.getRuntime().exec(new String[] { javaExecutable.getAbsolutePath(),
"-XshowSettings:properties", "-version" });
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
while ((version.isEmpty() || arch.isEmpty()) && (line = reader.readLine()) != null) {
line = line.trim();
// If the _JAVA_OPTIONS or JAVA_TOOL_OPTIONS environment variables are set, STDERR
// will start with "Picked up..." lines that need to be ignored so we can get to the
// java version line.
if (line.startsWith("Picked up")) {
continue;
}
String[] parts = line.split("\\s");
if (parts.length < 3) {
throw new ParseException("Failed to parse version: " + line, 0);
String searchString = "java.version = ";
if (line.startsWith(searchString)) {
version = line.substring(searchString.length());
}
searchString = "sun.arch.data.model = ";
if (line.startsWith(searchString)) {
arch = line.substring(searchString.length());
}
return new JavaVersion(parts[2]);
}
}
if (version.isEmpty()) {
throw new ParseException("Failed to find Java version", 0);
}
if (arch.isEmpty()) {
throw new ParseException("Failed to find Java architecture", 0);
}
return new JavaVersion(version, arch);
}
/**

View file

@ -19,22 +19,29 @@ import java.text.ParseException;
/**
* Class to more conveniently represent a Java version string.
* <p>
* Note: this class has a natural ordering that is inconsistent with equals
* (the <code>architecture</code> part of the version is disregarded in the
* {@link #compareTo(JavaVersion)} method).
*/
public class JavaVersion implements Comparable<JavaVersion> {
private int major;
private int minor;
private int patch;
private int arch;
/**
* Creates a new {@link JavaVersion} object from the given version string.
*
* @param version A version string.
* @throws ParseException if the version string failed to parse. The exception's
* message has more detailed information about why it failed.
* @param architecture An architecture string (32 or 64).
* @throws ParseException if the version or architecture string failed to parse.
* The exception's message has more detailed information about why it failed.
*/
public JavaVersion(String version) throws ParseException {
parse(version);
public JavaVersion(String version, String architecture) throws ParseException {
parseVersion(version);
parseArchitecture(architecture);
}
/**
@ -64,12 +71,21 @@ public class JavaVersion implements Comparable<JavaVersion> {
return patch;
}
/**
* Gets the architecture.
*
* @return The architecture.
*/
public int getArchitecture() {
return arch;
}
@Override
public String toString() {
if (major < 9) {
return String.format("1.%d.%d_%d", major, minor, patch);
return String.format("1.%d.%d_%d (%d-bit)", major, minor, patch, arch);
}
return String.format("%d.%d.%d", major, minor, patch);
return String.format("%d.%d.%d (%d-bit)", major, minor, patch, arch);
}
@Override
@ -102,6 +118,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
result = prime * result + major;
result = prime * result + minor;
result = prime * result + patch;
result = prime * result + arch;
return result;
}
@ -126,6 +143,9 @@ public class JavaVersion implements Comparable<JavaVersion> {
if (patch != other.patch) {
return false;
}
if (arch != other.arch) {
return false;
}
return true;
}
@ -136,7 +156,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
* @throws ParseException if the version string failed to parse. The exception's message
* has more detailed information about why it failed.
*/
private void parse(String version) throws ParseException {
private void parseVersion(String version) throws ParseException {
if (version == null) {
throw new ParseException("Version is null", 0);
}
@ -155,26 +175,26 @@ public class JavaVersion implements Comparable<JavaVersion> {
}
String[] versionParts = version.split("[._]");
int firstValue = parse(versionParts[0], "first value");
int firstValue = parseVersionPart(versionParts[0], "first value");
if (firstValue == 1) {
// Follows the Java 8 and earlier format of 1.major.minor_patch
if (versionParts.length > 1) {
major = parse(versionParts[1], "major");
major = parseVersionPart(versionParts[1], "major");
if (versionParts.length > 2) {
minor = parse(versionParts[2], "minor");
minor = parseVersionPart(versionParts[2], "minor");
if (versionParts.length > 3) {
patch = parse(versionParts[3], "patch");
patch = parseVersionPart(versionParts[3], "patch");
}
}
}
}
else if (firstValue >= 9) {
// Follows the Java 9 and later format of major.minor.patch
major = parse(versionParts[0], "major");
major = parseVersionPart(versionParts[0], "major");
if (versionParts.length > 1) {
minor = parse(versionParts[1], "minor");
minor = parseVersionPart(versionParts[1], "minor");
if (versionParts.length > 2) {
patch = parse(versionParts[2], "patch");
patch = parseVersionPart(versionParts[2], "patch");
}
}
}
@ -192,7 +212,7 @@ public class JavaVersion implements Comparable<JavaVersion> {
* @throws ParseException if the version part string failed to parse to a valid version part
* integer.
*/
private int parse(String versionPart, String versionPartName) throws ParseException {
private int parseVersionPart(String versionPart, String versionPartName) throws ParseException {
try {
int i = Integer.parseInt(versionPart);
if (i < 0) {
@ -205,4 +225,19 @@ public class JavaVersion implements Comparable<JavaVersion> {
0);
}
}
/**
* Parses the architecture integer out of the given architecture string.
*
* @param architecture An architecture string.
* @throws ParseException if the architecture string failed to parse.
*/
private void parseArchitecture(String architecture) throws ParseException {
try {
arch = Integer.parseInt(architecture);
}
catch (NumberFormatException e) {
throw new ParseException("Failed to parse architecture: " + architecture, 0);
}
}
}

View file

@ -28,6 +28,7 @@ public class WindowsJavaFinder extends JavaFinder {
protected List<File> getJavaRootInstallDirs() {
List<File> javaRootInstallDirs = new ArrayList<>();
javaRootInstallDirs.add(new File("C:\\Program Files\\Java"));
javaRootInstallDirs.add(new File("C:\\Program Files\\Amazon Corretto"));
return javaRootInstallDirs;
}