Skip to content

8359830: Incorrect os.version reported on macOS Tahoe 26 (Beta) #25865

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 35 additions & 17 deletions src/java.base/macosx/native/libjava/java_props_macosx.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
Expand All @@ -23,6 +23,7 @@
* questions.
*/

#include <stdbool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
Expand Down Expand Up @@ -229,33 +230,50 @@ void setOSNameAndVersion(java_props_t *sprops) {
NSString *nsVerStr = NULL;
char* osVersionCStr = NULL;
NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion];
// Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x)
// or explicitly requesting version compatibility
if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) ||
(getenv("SYSTEM_VERSION_COMPAT") != NULL)) {
if (osVer.patchVersion == 0) { // Omit trailing ".0"
// Some macOS versions require special handling. For example,
// when the NSOperatingSystemVersion reports 10.16 as the version
// then it should be treated as 11. Similarly, when it reports 16.0
// as the version then it should be treated as 26.
// If the SYSTEM_VERSION_COMPAT environment variable (a macOS construct)
// is set to 1, then we don't do any special handling for any versions
// and just literally use the value that NSOperatingSystemVersion reports.
const char* envVal = getenv("SYSTEM_VERSION_COMPAT");
const bool versionCompatEnabled = envVal != NULL
&& strncmp(envVal, "1", 1) == 0;
const bool requiresSpecialHandling =
((long) osVer.majorVersion == 10 && (long) osVer.minorVersion >= 16)
|| ((long) osVer.majorVersion == 16 && (long) osVer.minorVersion >= 0);
if (!requiresSpecialHandling || versionCompatEnabled) {
// no special handling - just use the version reported
// by NSOperatingSystemVersion
if (osVer.patchVersion == 0) {
// Omit trailing ".0"
nsVerStr = [NSString stringWithFormat:@"%ld.%ld",
(long)osVer.majorVersion, (long)osVer.minorVersion];
} else {
nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld",
(long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion];
(long)osVer.majorVersion, (long)osVer.minorVersion,
(long)osVer.patchVersion];
}
} else {
// Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT
// AKA 11+ Read the *real* ProductVersion from the hidden link to avoid SYSTEM_VERSION_COMPAT
// If not found, fallback below to the SystemVersion.plist
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
@"/System/Library/CoreServices/.SystemVersionPlatform.plist"];
// Requires special handling. We ignore the version reported
// by the NSOperatingSystemVersion API and instead read the
// *real* ProductVersion from
// /System/Library/CoreServices/.SystemVersionPlatform.plist.
// If not found there, then as a last resort we fallback to
// /System/Library/CoreServices/SystemVersion.plist
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:
@"/System/Library/CoreServices/.SystemVersionPlatform.plist"];
if (version != NULL) {
nsVerStr = [version objectForKey : @"ProductVersion"];
nsVerStr = [version objectForKey: @"ProductVersion"];
}
}
// Fallback to reading the SystemVersion.plist
// Last resort - fallback to reading the SystemVersion.plist
if (nsVerStr == NULL) {
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile :
@"/System/Library/CoreServices/SystemVersion.plist"];
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:
@"/System/Library/CoreServices/SystemVersion.plist"];
if (version != NULL) {
nsVerStr = [version objectForKey : @"ProductVersion"];
nsVerStr = [version objectForKey: @"ProductVersion"];
}
}

Expand Down
54 changes: 32 additions & 22 deletions test/jdk/java/lang/System/OsVersionTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015, 2021 SAP SE. All rights reserved.
* 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
Expand Down Expand Up @@ -28,56 +29,65 @@

/*
* @test
* @bug 8132374
* @bug 8132374 8359830
* @summary Check that the value of the os.version property is equal
* to the value of the corresponding OS provided tools.
* @library /test/lib
* @build jtreg.SkippedException
* @run main OsVersionTest
* @author Volker Simonis
*/
public class OsVersionTest {

public static void main(String args[]) throws Throwable {
public static void main(String[] args) throws Throwable {
final String osVersion = System.getProperty("os.version");
if (osVersion == null) {
throw new Error("Cant query 'os.version' property!");
throw new Error("Missing value for os.version system property");
}
if (Platform.isLinux()) {
OutputAnalyzer output = ProcessTools.executeProcess("uname", "-r");
output.shouldHaveExitValue(0);
if (!osVersion.equals(output.getOutput().trim())) {
throw new Error(osVersion + " != " + output.getOutput().trim());
}
}
else if (Platform.isOSX()) {
OutputAnalyzer output = ProcessTools.executeProcess("sw_vers", "-productVersion");
String swVersOutput = output.getOutput().trim();
if (!osVersion.equals(swVersOutput)) {
// This section can be removed if minimum build SDK is xcode 12+
if (swVersOutput.startsWith(osVersion)) {
throw new SkippedException("MacOS version only matches in parts, this is expected when " +
"JDK was built with Xcode < 12 and MacOS version patch is > 0");
}
throw new Error(osVersion + " != " + swVersOutput);
}
}
else if (Platform.isAix()) {
} else if (Platform.isOSX()) {
testMacOS(osVersion);
} else if (Platform.isAix()) {
OutputAnalyzer output1 = ProcessTools.executeProcess("uname", "-v");
output1.shouldHaveExitValue(0);
OutputAnalyzer output2 = ProcessTools.executeProcess("uname", "-r");
output2.shouldHaveExitValue(0);
String version = output1.getOutput().trim() + "." + output2.getOutput().trim();
if (!osVersion.equals(version)) {
throw new Error(osVersion + " != " + version);
}
}
else if (Platform.isWindows()) {
} else if (Platform.isWindows()) {
OutputAnalyzer output = ProcessTools.executeProcess("cmd", "/c", "ver");
output.shouldHaveExitValue(0);
String version = output.firstMatch(".+\\[Version ([0-9.]+)\\]", 1);
if (version == null || !version.startsWith(osVersion)) {
throw new Error(osVersion + " != " + version);
}
}
else {
System.out.println("This test is currently not supported on " +
} else {
throw new jtreg.SkippedException("This test is currently not supported on " +
Platform.getOsName());
}
}

private static void testMacOS(final String sysPropOsVersion) throws Exception {
final ProcessBuilder pb = new ProcessBuilder("sw_vers", "-productVersion");
// if the test was launched with SYSTEM_VERSION_COMPAT environment variable set,
// then propagate that to the sw_vers too
final String versionCompat = System.getenv().get("SYSTEM_VERSION_COMPAT");
if (versionCompat != null) {
pb.environment().put("SYSTEM_VERSION_COMPAT", versionCompat);
}
final OutputAnalyzer output = ProcessTools.executeCommand(pb);
output.shouldHaveExitValue(0);
final String swVersOutput = output.getOutput().trim();
if (!sysPropOsVersion.equals(swVersOutput)) {
throw new Error("sw_vers reports macOS version: " + swVersOutput
+ " but os.version system property reports version: " + sysPropOsVersion);
}
}
}