8348986: Improve coverage of enhanced exception messages

Reviewed-by: dfuchs
This commit is contained in:
Michael McMahon 2025-06-03 15:36:29 +00:00
parent 01f01b6f7b
commit b6f827ef05
47 changed files with 883 additions and 275 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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
@ -29,6 +29,9 @@ import java.util.Formatter;
import java.util.Locale;
import sun.net.util.IPAddressUtil;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* Parses a string containing a host/domain name and port range
*/
@ -56,7 +59,7 @@ class HostPortrange {
return hostname.hashCode() + portrange[0] + portrange[1];
}
HostPortrange(String scheme, String str) {
HostPortrange(String scheme, String host) {
// Parse the host name. A name has up to three components, the
// hostname, a port number, or two numbers representing a port
// range. "www.example.com:8080-9090" is a valid host name.
@ -67,21 +70,23 @@ class HostPortrange {
// Refer to RFC 2732 for more information.
// first separate string into two fields: hoststr, portstr
String hoststr, portstr = null;
String hoststr = null, portstr = null;
this.scheme = scheme;
// check for IPv6 address
if (str.charAt(0) == '[') {
if (host.charAt(0) == '[') {
ipv6 = literal = true;
int rb = str.indexOf(']');
int rb = host.indexOf(']');
if (rb != -1) {
hoststr = str.substring(1, rb);
hoststr = host.substring(1, rb);
} else {
throw new IllegalArgumentException("invalid IPv6 address: " + str);
throw new IllegalArgumentException(
formatMsg("invalid IPv6 address%s",
filterNonSocketInfo(host).prefixWith(": ")));
}
int sep = str.indexOf(':', rb + 1);
if (sep != -1 && str.length() > sep) {
portstr = str.substring(sep + 1);
int sep = host.indexOf(':', rb + 1);
if (sep != -1 && host.length() > sep) {
portstr = host.substring(sep + 1);
}
// need to normalize hoststr now
byte[] ip = IPAddressUtil.textToNumericFormatV6(hoststr);
@ -94,16 +99,16 @@ class HostPortrange {
+ "%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8],
ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]);
hostname = sb.toString();
this.hostname = sb.toString();
} else {
// not IPv6 therefore ':' is the port separator
int sep = str.indexOf(':');
if (sep != -1 && str.length() > sep) {
hoststr = str.substring(0, sep);
portstr = str.substring(sep + 1);
int sep = host.indexOf(':');
if (sep != -1 && host.length() > sep) {
hoststr = host.substring(0, sep);
portstr = host.substring(sep + 1);
} else {
hoststr = sep == -1 ? str : str.substring(0, sep);
hoststr = sep == -1 ? host : host.substring(0, sep);
}
// is this a domain wildcard specification?
if (hoststr.lastIndexOf('*') > 0) {
@ -150,13 +155,14 @@ class HostPortrange {
}
}
}
hostname = hoststr;
this.hostname = hoststr;
}
try {
portrange = parsePort(portstr);
} catch (Exception e) {
throw new IllegalArgumentException("invalid port range: " + portstr);
throw new IllegalArgumentException(
formatMsg("invalid port range%s", filterNonSocketInfo(portstr).prefixWith(": ")));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -27,6 +27,8 @@ import java.io.IOException;
import java.net.spi.InetAddressResolver.LookupPolicy;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/*
* Package private implementation of InetAddressImpl for IPv4.
@ -38,7 +40,7 @@ final class Inet4AddressImpl implements InetAddressImpl {
public InetAddress[] lookupAllHostAddr(String hostname, LookupPolicy lookupPolicy)
throws UnknownHostException {
if ((lookupPolicy.characteristics() & IPV4) == 0) {
throw new UnknownHostException(hostname);
throw new UnknownHostException(formatMsg("%s", filterNonSocketInfo(hostname)));
}
return lookupAllHostAddr(hostname);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
@ -35,6 +35,8 @@ import java.io.ObjectStreamField;
import java.util.Enumeration;
import java.util.Arrays;
import java.util.Objects;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class represents an Internet Protocol version 6 (IPv6) address.
@ -581,7 +583,9 @@ class Inet6Address extends InetAddress {
if (addrBytes.length == Inet4Address.INADDRSZ) {
if (numericZone != -1 || ifname != null) {
// IPv4-mapped address must not contain zone-id
throw new UnknownHostException(addressLiteral + ": invalid IPv4-mapped address");
throw new UnknownHostException(
formatMsg("%sinvalid IPv4-mapped address",
filterNonSocketInfo(addressLiteral).suffixWith(": ")));
}
return new Inet4Address(null, addrBytes);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -54,6 +54,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
import jdk.internal.util.Exceptions;
import jdk.internal.access.JavaNetInetAddressAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Blocker;
@ -68,6 +69,8 @@ import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4_FIRST;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class represents an Internet Protocol (IP) address.
@ -382,6 +385,7 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
}
}
);
Exceptions.setup(); // needed for native exceptions
init();
}
@ -902,7 +906,7 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
@Override
public InetAddress[] get() throws UnknownHostException {
if (inetAddresses == null) {
throw new UnknownHostException(host);
throw new UnknownHostException(formatMsg("%s", filterNonSocketInfo(host)));
}
return inetAddresses;
}
@ -1095,7 +1099,9 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
}
}
if (inetAddresses == null || inetAddresses.length == 0) {
throw ex == null ? new UnknownHostException(host) : ex;
throw ex == null
? new UnknownHostException(formatMsg("%s", filterNonSocketInfo(host)))
: ex;
}
return inetAddresses;
}
@ -1203,16 +1209,19 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
}
}
} catch (IOException e) {
throw new UnknownHostException("Unable to resolve address "
+ Arrays.toString(addr) + " as hosts file " + hostsFile
+ " not found ");
throw new UnknownHostException(
formatMsg("Unable to resolve address %s as hosts file %s not found",
filterNonSocketInfo(Arrays.toString(addr)),
filterNonSocketInfo(hostsFile)
.replaceWith("from ${jdk.net.hosts.file} system property")));
}
if ((host == null) || (host.isEmpty()) || (host.equals(" "))) {
throw new UnknownHostException("Requested address "
+ Arrays.toString(addr)
+ " resolves to an invalid entry in hosts file "
+ hostsFile);
throw new UnknownHostException(
formatMsg("Requested address %s resolves to an invalid entry in hosts file %s",
filterNonSocketInfo(Arrays.toString(addr)),
filterNonSocketInfo(hostsFile)
.replaceWith("from ${jdk.net.hosts.file} system property")));
}
return host;
}
@ -1273,8 +1282,11 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
}
}
} catch (IOException e) {
throw new UnknownHostException("Unable to resolve host " + host
+ " as hosts file " + hostsFile + " not found ");
throw new UnknownHostException(
formatMsg("Unable to resolve host %s as hosts file %s not found",
filterNonSocketInfo(host), filterNonSocketInfo(hostsFile)
.replaceWith("from ${jdk.net.hosts.file} system property")));
}
// Check if only IPv4 addresses are requested
if (needIPv4 && !needIPv6) {
@ -1305,8 +1317,10 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
private void checkResultsList(List<InetAddress> addressesList, String hostName)
throws UnknownHostException {
if (addressesList.isEmpty()) {
throw new UnknownHostException("Unable to resolve host " + hostName
+ " in hosts file " + hostsFile);
throw new UnknownHostException(
formatMsg("Unable to resolve host %s in hosts file %s",
filterNonSocketInfo(hostName), filterNonSocketInfo(hostsFile)
.replaceWith("from ${jdk.net.hosts.file} system property")));
}
}
@ -1543,7 +1557,7 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
// Here we check the address string for ambiguity only
inetAddress = Inet4Address.parseAddressString(host, false);
} catch (IllegalArgumentException iae) {
var uhe = new UnknownHostException(host);
var uhe = new UnknownHostException(formatMsg("%s", filterNonSocketInfo(host)));
uhe.initCause(iae);
throw uhe;
}
@ -1570,7 +1584,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) {
String hostString = wrapInBrackets ? "[" + host + "]" : host;
return new UnknownHostException(hostString + ": invalid IPv6 address literal");
return new UnknownHostException(formatMsg("%sinvalid IPv6 address literal",
filterNonSocketInfo(hostString).suffixWith(": ")));
}
/**
@ -1708,7 +1723,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
InetAddress[] result = addresses == null ? null
: addresses.toArray(InetAddress[]::new);
if (result == null || result.length == 0) {
throw ex == null ? new UnknownHostException(host) : ex;
throw ex == null ? new UnknownHostException(formatMsg("%s", filterNonSocketInfo(host)))
: ex;
}
return result;
}
@ -1781,8 +1797,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
} catch (UnknownHostException uhe) {
// Rethrow with a more informative error message.
UnknownHostException uhe2 =
new UnknownHostException(local + ": " +
uhe.getMessage());
new UnknownHostException(formatMsg(filterNonSocketInfo(local)
.suffixWith(": ") + uhe.getMessage()));
uhe2.initCause(uhe);
throw uhe2;
}

View File

@ -34,6 +34,8 @@ import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class represents a Network Interface.
@ -323,7 +325,9 @@ public final class NetworkInterface {
+ addr.holder.family);
}
} else {
throw new IllegalArgumentException("invalid address type: " + addr);
throw new IllegalArgumentException(
formatMsg("invalid address type%s",
filterNonSocketInfo(addr.toString()).prefixWith(": ")));
}
return getByInetAddress0(addr);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -26,6 +26,8 @@
package java.net;
import java.util.Objects;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class represents a proxy setting, typically a type (http, socks) and
@ -93,8 +95,11 @@ public class Proxy {
* incompatible
*/
public Proxy(Type type, SocketAddress sa) {
if ((type == Type.DIRECT) || !(sa instanceof InetSocketAddress))
throw new IllegalArgumentException("type " + type + " is not compatible with address " + sa);
if ((type == Type.DIRECT) || !(sa instanceof InetSocketAddress)) {
throw new IllegalArgumentException(
formatMsg("type " + type + " is not compatible with address %s",
filterNonSocketInfo(String.valueOf(sa))));
}
this.type = type;
this.sa = sa;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -46,6 +46,8 @@ import sun.security.util.RegisteredDomain;
import sun.security.util.SecurityConstants;
import sun.security.util.Debug;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class represents access to a network via sockets.
@ -392,8 +394,8 @@ public final class SocketPermission extends Permission
if (rb != -1) {
host = host.substring(start, rb);
} else {
throw new
IllegalArgumentException("invalid host/port: "+host);
throw new IllegalArgumentException(
formatMsg("invalid host/port%s", filterNonSocketInfo(host).prefixWith(": ")));
}
sep = hostport.indexOf(':', rb+1);
} else {
@ -410,8 +412,8 @@ public final class SocketPermission extends Permission
try {
portrange = parsePort(port);
} catch (Exception e) {
throw new
IllegalArgumentException("invalid port range: "+port);
throw new IllegalArgumentException(
formatMsg("invalid port range%s", filterNonSocketInfo(port).prefixWith(": ")));
}
} else {
portrange = new int[] { PORT_MIN, PORT_MAX };
@ -784,7 +786,7 @@ public final class SocketPermission extends Permission
throw uhe;
} catch (IndexOutOfBoundsException iobe) {
invalid = true;
throw new UnknownHostException(getName());
throw new UnknownHostException(formatMsg("%s", filterNonSocketInfo(getName())));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
@ -37,6 +37,8 @@ import sun.net.spi.DefaultProxySelector;
import sun.net.www.ParseUtil;
import static sun.net.util.IPAddressUtil.isIPv6LiteralAddress;
import static jdk.internal.util.Exceptions.filterSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* SOCKS (V4 & V5) TCP socket implementation (RFC 1928).
@ -330,7 +332,7 @@ class SocksSocketImpl extends DelegatingSocketImpl implements SocksConsts {
// SOCKS Protocol version 4 doesn't know how to deal with
// DOMAIN type of addresses (unresolved addresses here)
if (epoint.isUnresolved())
throw new UnknownHostException(epoint.toString());
throw new UnknownHostException(formatMsg("%s", filterSocketInfo(epoint.toString())));
connectV4(in, out, epoint, deadlineMillis);
return;
}
@ -349,7 +351,7 @@ class SocksSocketImpl extends DelegatingSocketImpl implements SocksConsts {
// SOCKS Protocol version 4 doesn't know how to deal with
// DOMAIN type of addresses (unresolved addresses here)
if (epoint.isUnresolved())
throw new UnknownHostException(epoint.toString());
throw new UnknownHostException(formatMsg("%s", filterSocketInfo(epoint.toString())));
connectV4(in, out, epoint, deadlineMillis);
return;
}

View File

@ -42,8 +42,12 @@ import java.nio.file.Path;
import java.text.Normalizer;
import jdk.internal.access.JavaNetUriAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.Exceptions;
import sun.nio.cs.UTF_8;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* Represents a Uniform Resource Identifier (URI) reference.
*
@ -2032,7 +2036,8 @@ public final class URI
{
if (scheme != null) {
if (path != null && !path.isEmpty() && path.charAt(0) != '/')
throw new URISyntaxException(s, "Relative path in absolute URI");
throw new URISyntaxException(formatMsg("%s", filterNonSocketInfo(s)),
"Relative path in absolute URI");
}
}
@ -2988,11 +2993,14 @@ public final class URI
// -- Methods for throwing URISyntaxException in various ways --
private void fail(String reason) throws URISyntaxException {
throw new URISyntaxException(input, reason);
throw new URISyntaxException(formatMsg("%s", filterNonSocketInfo(input)), reason);
}
private void fail(String reason, int p) throws URISyntaxException {
throw new URISyntaxException(input, reason, p);
if (!Exceptions.enhancedNonSocketExceptions()) {
p = -1;
}
throw new URISyntaxException(formatMsg("%s", filterNonSocketInfo(input)), reason, p);
}
private void failExpecting(String expected, int p)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -44,6 +44,8 @@ import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.ThreadTracker;
import jdk.internal.misc.VM;
import sun.net.util.IPAddressUtil;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* Class {@code URL} represents a Uniform Resource
@ -1168,7 +1170,8 @@ public final class URL implements java.io.Serializable {
URI uri = new URI(toString());
if (authority != null && isBuiltinStreamHandler(handler)) {
String s = IPAddressUtil.checkAuthority(this);
if (s != null) throw new URISyntaxException(authority, s);
if (s != null)
throw new URISyntaxException(formatMsg("%s", filterNonSocketInfo(authority)), s);
}
return uri;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -30,6 +30,9 @@ import java.util.Locale;
import java.util.Objects;
import sun.net.util.IPAddressUtil;
import static jdk.internal.util.Exceptions.formatMsg;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
/**
* The abstract class {@code URLStreamHandler} is the common
* superclass for all stream protocol handlers. A stream protocol
@ -206,7 +209,7 @@ public abstract class URLStreamHandler {
if (!IPAddressUtil.
isIPv6LiteralAddress(host.substring(1, ind))) {
throw new IllegalArgumentException(
"Invalid host: "+ host);
formatMsg("Invalid host%s", filterNonSocketInfo(host).prefixWith(": ")));
}
port = -1 ;
@ -220,12 +223,14 @@ public abstract class URLStreamHandler {
}
} else {
throw new IllegalArgumentException(
"Invalid authority field: " + authority);
formatMsg("Invalid authority field%s",
filterNonSocketInfo(authority).prefixWith(": ")));
}
}
} else {
throw new IllegalArgumentException(
"Invalid authority field: " + authority);
formatMsg("Invalid authority field%s",
filterNonSocketInfo(authority).prefixWith(": ")));
}
} else {
ind = host.indexOf(':');

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2018, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package jdk.internal.util;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnixDomainSocketAddress;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.stream.Stream;
import sun.security.util.SecurityProperties;
import jdk.internal.misc.VM;
/**
* Contains static utility methods which can filter exception
* message strings for sensitive information.
*
* Code using this mechanism should use formatMsg()
* to generate a formatted (enhanced or restricted) string for exception
* messages.
*
* The methods above take variable numbers of SensitiveInfo objects
* as parameters which contain the text that may have to be filtered.
*
* The SensitiveInfo objects should be generated with one of the following:
* public static SensitiveInfo filterSocketInfo(String s)
* public static SensitiveInfo filterNonSocketInfo(String s)
* public static SensitiveInfo filterJarName(String name)
* public static SensitiveInfo filterUserName(String name)
*/
public final class Exceptions {
private Exceptions() {}
private static volatile boolean enhancedSocketExceptionText;
private static volatile boolean enhancedNonSocketExceptionText;
private static volatile boolean enhancedUserExceptionText;
private static volatile boolean enhancedJarExceptionText;
private static volatile boolean initialized = false;
/**
* Base class for generating exception messages that may
* contain sensitive information which in certain contexts
* needs to be filtered out, in case it gets revealed in
* unexpected places. Exception messages are either enhanced
* or restricted. Enhanced messages include sensitive information.
* Restricted messages don't.
*
* Sub-class for any new category that needs to be independently
* controlled. Consider using a unique value for the
* SecurityProperties.includedInExceptions(String value) mechanism
* Current values defined are "jar", "userInfo"
* "hostInfo", "hostInfoExclSocket".
*
* New code can also piggy back on existing categories
*
* A SensitiveInfo contains the following components
* all of which default to empty strings.
*
* prefix, the sensitive info itself, a suffix
* and a replacement string.
*
* The composeFilteredText(boolean enhance) method generates
* an enhanced string when enhance is true.
* This comprises (enhance == true)
* prefix + info + suffix
* When (enhance == false), then by default the output is:
* "" empty string
* However, if a replacement is set, then when enhance == false
* the output is the replacement string.
*/
public abstract static class SensitiveInfo {
String info, suffix, prefix, replacement;
boolean enhanced;
SensitiveInfo(String info) {
this.info = info;
prefix = suffix = replacement = "";
}
public SensitiveInfo prefixWith(String prefix) {
this.prefix = prefix;
return this;
}
public SensitiveInfo suffixWith(String suffix) {
this.suffix = suffix;
return this;
}
public SensitiveInfo replaceWith(String replacement) {
this.replacement = replacement;
return this;
}
public boolean enhanced() {
return enhanced;
}
/**
* Implementation should call composeFilteredText(boolean flag)
* where flag contains the boolean value of whether
* the category is enabled or not.
*/
public abstract String output();
protected String composeFilteredText(boolean enhance) {
if (enhance) {
this.enhanced = true;
return prefix + info + suffix;
} else {
return replacement;
}
}
}
static final class SocketInfo extends SensitiveInfo {
public SocketInfo(String host) {
super(host);
}
@Override
public String output() {
setup();
return super.composeFilteredText(enhancedSocketExceptionText);
}
}
static final class NonSocketInfo extends SensitiveInfo {
public NonSocketInfo(String host) {
super(host);
}
@Override
public String output() {
setup();
return super.composeFilteredText(enhancedNonSocketExceptionText);
}
}
static final class JarInfo extends SensitiveInfo {
public JarInfo(String name) {
super(name);
}
@Override
public String output() {
setup();
return super.composeFilteredText(enhancedJarExceptionText);
}
}
static final class UserInfo extends SensitiveInfo {
public UserInfo(String host) {
super(host);
}
@Override
public String output() {
setup();
return super.composeFilteredText(enhancedUserExceptionText);
}
}
// remove leading, trailing and duplicated space characters
static String trim(String s) {
int len = s.length();
if (len == 0) return s;
StringBuilder sb = new StringBuilder();
// initial value deals with leading spaces
boolean inSpace = true;
for (int i=0; i<len; i++) {
char c = s.charAt(i);
if (c == ' ') {
if (inSpace)
continue;
inSpace = true;
} else
inSpace = false;
sb.append(c);
}
int sblen = sb.length();
// last char could be a space
if (sblen > 0 && sb.charAt(sblen - 1) == ' ')
sb.deleteCharAt(sblen - 1);
return sb.toString();
}
public static SensitiveInfo filterSocketInfo(String host) {
return new SocketInfo(host);
}
public static SensitiveInfo filterNonSocketInfo(String host) {
return new NonSocketInfo(host);
}
public static SensitiveInfo filterJarName(String name) {
return new JarInfo(name);
}
public static SensitiveInfo filterUserName(String name) {
return new UserInfo(name);
}
/**
* Transform each SensitiveInfo into a String argument which is passed
* to String.format(). This string is then trimmed.
*/
public static String formatMsg(String format, SensitiveInfo... infos) {
String[] args = new String[infos.length];
int i = 0;
for (SensitiveInfo info : infos) {
args[i++] = info.output();
}
return trim(String.format(format, (Object[])args));
}
/**
* Simplification of above. Equivalent to:
* formatMsg("%s", SensitiveInfo[1]); // ie with one arg
*/
public static String formatMsg(SensitiveInfo info) {
return trim(info.output());
}
public static void setup() {
if (initialized || !VM.isBooted())
return;
enhancedSocketExceptionText = SecurityProperties.includedInExceptions("hostInfo");
enhancedNonSocketExceptionText = SecurityProperties.includedInExceptions("hostInfoExclSocket")
| enhancedSocketExceptionText;
enhancedUserExceptionText = SecurityProperties.includedInExceptions("userInfo");
enhancedJarExceptionText = SecurityProperties.INCLUDE_JAR_NAME_IN_EXCEPTIONS;
initialized = true;
}
public static boolean enhancedNonSocketExceptions() {
setup();
return enhancedNonSocketExceptionText;
}
public static boolean enhancedSocketExceptions() {
setup();
return enhancedSocketExceptionText;
}
/**
* The enhanced message text is the socket address appended to
* the original IOException message
*/
public static IOException ioException(IOException e, SocketAddress addr) {
setup();
if (addr == null) {
return e;
}
if (!enhancedSocketExceptionText) {
return create(e, e.getMessage());
}
if (addr instanceof UnixDomainSocketAddress) {
return ofUnixDomain(e, (UnixDomainSocketAddress)addr);
} else if (addr instanceof InetSocketAddress) {
return ofInet(e, (InetSocketAddress)addr);
} else {
return e;
}
}
private static IOException ofInet(IOException e, InetSocketAddress addr) {
return create(e, String.join(": ", e.getMessage(), addr.toString()));
}
private static IOException ofUnixDomain(IOException e, UnixDomainSocketAddress addr) {
String path = addr.getPath().toString();
StringBuilder sb = new StringBuilder();
sb.append(e.getMessage());
sb.append(": ");
sb.append(path);
String enhancedMsg = sb.toString();
return create(e, enhancedMsg);
}
// return a new instance of the same type with the given detail
// msg, or if the type doesn't support detail msgs, return given
// instance.
private static <T extends Exception> T create(T e, String msg) {
try {
Class<? extends Exception> clazz = e.getClass();
@SuppressWarnings("unchecked")
Constructor<T> ctor = (Constructor<T>)clazz.getConstructor(String.class);
T e1 = (ctor.newInstance(msg));
e1.setStackTrace(e.getStackTrace());
return e1;
} catch (Exception e0) {
// Some eg AsynchronousCloseException have no detail msg
return e;
}
}
}

View File

@ -270,9 +270,13 @@ module java.base {
java.prefs,
java.security.jgss,
java.smartcardio,
java.naming,
java.rmi,
java.net.http,
jdk.charsets,
jdk.incubator.vector,
jdk.internal.vm.ci,
jdk.httpserver,
jdk.jlink,
jdk.jpackage,
jdk.net;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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
@ -37,6 +37,9 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import static jdk.internal.util.Exceptions.formatMsg;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
public class IPAddressUtil {
private static final int INADDR4SZ = 4;
private static final int INADDR16SZ = 16;
@ -161,7 +164,8 @@ public class IPAddressUtil {
* @return an {@code IllegalArgumentException} instance
*/
public static IllegalArgumentException invalidIpAddressLiteral(String src) {
return new IllegalArgumentException("Invalid IP address literal: " + src);
return new IllegalArgumentException(
formatMsg("Invalid IP address literal%s", filterNonSocketInfo(src).prefixWith(": ")));
}
/*

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2018, 2024, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.net.util;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.InetSocketAddress;
import java.net.UnixDomainSocketAddress;
import java.net.SocketAddress;
import sun.security.util.SecurityProperties;
public final class SocketExceptions {
private SocketExceptions() {}
private static final boolean enhancedExceptionText =
SecurityProperties.includedInExceptions("hostInfo");
/**
* Utility which takes an exception and returns either the same exception
* or a new exception of the same type with the same stack trace
* and detail message enhanced with addressing information from the
* given InetSocketAddress.
*
* If the system/security property "jdk.includeInExceptions" is not
* set or does not contain the category hostInfo,
* then the original exception is returned.
*
* Only specific IOException subtypes are supported.
*/
public static IOException of(IOException e, SocketAddress addr) {
if (!enhancedExceptionText || addr == null) {
return e;
}
if (addr instanceof UnixDomainSocketAddress) {
return ofUnixDomain(e, (UnixDomainSocketAddress)addr);
} else if (addr instanceof InetSocketAddress) {
return ofInet(e, (InetSocketAddress)addr);
} else {
return e;
}
}
private static IOException ofInet(IOException e, InetSocketAddress addr) {
return create(e, String.join(": ", e.getMessage(), addr.toString()));
}
private static IOException ofUnixDomain(IOException e, UnixDomainSocketAddress addr) {
String path = addr.getPath().toString();
StringBuilder sb = new StringBuilder();
sb.append(e.getMessage());
sb.append(": ");
sb.append(path);
String enhancedMsg = sb.toString();
return create(e, enhancedMsg);
}
// return a new instance of the same type with the given detail
// msg, or if the type doesn't support detail msgs, return given
// instance.
private static IOException create(final IOException e, final String msg) {
try {
Class<?> clazz = e.getClass();
Constructor<?> ctor = clazz.getConstructor(String.class);
IOException e1 = (IOException)(ctor.newInstance(msg));
e1.setStackTrace(e.getStackTrace());
return e1;
} catch (Exception e0) {
// Some eg AsynchronousCloseException have no detail msg
return e;
}
}
}

View File

@ -40,6 +40,8 @@ import java.nio.charset.CodingErrorAction;
import java.util.HexFormat;
import sun.nio.cs.UTF_8;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* A class that contains useful routines common to sun.net.www
@ -502,7 +504,7 @@ public final class ParseUtil {
{
if (scheme != null) {
if (path != null && !path.isEmpty() && path.charAt(0) != '/')
throw new URISyntaxException(s,
throw new URISyntaxException(formatMsg("%s", filterNonSocketInfo(s)),
"Relative path in absolute URI");
}
}

View File

@ -53,7 +53,8 @@ import sun.security.ssl.SSLSocketImpl;
import sun.util.logging.PlatformLogger;
import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* This class provides HTTPS client URL support, building on the standard
@ -559,8 +560,10 @@ final class HttpsClient extends HttpClient
serverSocket.close();
session.invalidate();
throw new IOException("HTTPS hostname wrong: should be <"
+ url.getHost() + ">");
throw new IOException(formatMsg("Wrong HTTPS hostname%s",
filterNonSocketInfo(url.getHost())
.prefixWith(": should be <")
.suffixWith(">")));
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -27,6 +27,8 @@ package sun.net.www.protocol.jar;
import java.io.IOException;
import java.net.*;
import static jdk.internal.util.Exceptions.filterJarName;
import static jdk.internal.util.Exceptions.formatMsg;
/*
* Jar URL Handler
@ -181,8 +183,11 @@ public class Handler extends java.net.URLStreamHandler {
String innerSpec = spec.substring(0, index - 1);
newURL(innerSpec);
} catch (MalformedURLException e) {
throw new NullPointerException("invalid url: " +
spec + " (" + e + ")");
throw new NullPointerException(
formatMsg("invalid url: %s %s", filterJarName(spec),
filterJarName(e.getMessage())
.prefixWith("(")
.suffixWith(")")));
}
return spec;
}
@ -193,19 +198,18 @@ public class Handler extends java.net.URLStreamHandler {
if (spec.startsWith("/")) {
int bangSlash = indexOfBangSlash(ctxFile);
if (bangSlash == -1) {
throw new NullPointerException("malformed " +
"context url:" +
url +
": no !/");
throw new NullPointerException(
formatMsg("malformed context url%s : no !/",
filterJarName(String.valueOf(url)).prefixWith(": ")));
}
ctxFile = ctxFile.substring(0, bangSlash);
} else {
// chop up the last component
int lastSlash = ctxFile.lastIndexOf('/');
if (lastSlash == -1) {
throw new NullPointerException("malformed " +
"context url:" +
url);
throw new NullPointerException(
formatMsg("malformed context url%s",
filterJarName(String.valueOf(url)).prefixWith(": ")));
} else if (lastSlash < ctxFile.length() - 1) {
ctxFile = ctxFile.substring(0, lastSlash + 1);
}

View File

@ -35,6 +35,8 @@ import java.util.jar.JarFile;
import jdk.internal.util.OperatingSystem;
import sun.net.util.URLUtil;
import sun.net.www.ParseUtil;
import static jdk.internal.util.Exceptions.filterJarName;
import static jdk.internal.util.Exceptions.formatMsg;
/* A factory for cached JAR file. This class is used to both retrieve
* and cache Jar files.
@ -108,7 +110,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
result = URLJarFile.getJarFile(patched, this);
}
if (result == null)
throw new FileNotFoundException(url.toString());
throw new FileNotFoundException(formatMsg("%s", filterJarName(url.toString())));
return result;
}
@ -200,7 +202,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
result = URLJarFile.getJarFile(url, this);
}
if (result == null)
throw new FileNotFoundException(url.toString());
throw new FileNotFoundException(formatMsg("%s", filterJarName(url.toString())));
return result;
}

View File

@ -37,6 +37,9 @@ import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import static jdk.internal.util.Exceptions.filterJarName;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* @author Benjamin Renaud
@ -129,9 +132,10 @@ public class JarURLConnection extends java.net.JarURLConnection {
factory.closeIfNotCached(url, jarFile);
} catch (Exception e) {
}
throw new FileNotFoundException("JAR entry " + entryName +
" not found in " +
jarFile.getName());
throw new FileNotFoundException(
formatMsg("JAR entry %s not found in jar file %s",
filterJarName(entryName),
filterJarName(jarFile.getName())));
}
}
@ -169,9 +173,10 @@ public class JarURLConnection extends java.net.JarURLConnection {
throw new IOException("no entry name specified");
} else {
if (jarEntry == null) {
throw new FileNotFoundException("JAR entry " + entryName +
" not found in " +
jarFile.getName());
throw new FileNotFoundException(
formatMsg("JAR entry %s not found in jar file %s",
filterJarName(entryName),
filterJarName(jarFile.getName())));
}
result = new JarURLInputStream (jarFile.getInputStream(jarEntry));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
@ -53,6 +53,8 @@ import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static jdk.internal.util.Exceptions.formatMsg;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
/**
* A multicast datagram socket based on a datagram channel.
@ -490,7 +492,8 @@ public class DatagramSocketAdaptor
NetworkInterface ni = NetworkInterface.getByInetAddress(inf);
if (ni == null) {
String address = inf.getHostAddress();
throw new SocketException("No network interface with address " + address);
throw new SocketException(formatMsg("No network interface found with address %s",
filterNonSocketInfo(address)));
}
synchronized (outgoingInterfaceLock) {
// set interface and update cached values

View File

@ -58,10 +58,12 @@ import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.PlatformSocketImpl;
import sun.net.ext.ExtendedSocketOptions;
import sun.net.util.SocketExceptions;
import jdk.internal.util.Exceptions;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* NIO based SocketImpl.
@ -554,7 +556,8 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
throw new IOException("Unsupported address type");
InetSocketAddress isa = (InetSocketAddress) remote;
if (isa.isUnresolved()) {
throw new UnknownHostException(isa.getHostName());
throw new UnknownHostException(
formatMsg(filterNonSocketInfo(isa.getHostName())));
}
InetAddress address = isa.getAddress();
@ -604,7 +607,7 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
assert Thread.currentThread().isVirtual();
throw new SocketException("Closed by interrupt");
} else {
throw SocketExceptions.of(ioe, isa);
throw Exceptions.ioException(ioe, isa);
}
}
}

View File

@ -40,6 +40,9 @@ import java.nio.channels.SocketChannel;
import java.util.Set;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
// Make a socket channel look like a socket.
//
@ -92,7 +95,8 @@ class SocketAdaptor
if (sc.isConnected())
throw new SocketException("Already connected");
close();
throw new UnknownHostException(remote.toString());
throw new UnknownHostException(
formatMsg(filterNonSocketInfo(remote.toString())));
}
if (timeout < 0)
throw new IllegalArgumentException("connect: timeout can't be negative");

View File

@ -64,7 +64,7 @@ import jdk.internal.event.SocketWriteEvent;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions;
import sun.net.util.SocketExceptions;
import jdk.internal.util.Exceptions;
/**
* An implementation of SocketChannels
@ -975,7 +975,7 @@ class SocketChannelImpl
} catch (IOException ioe) {
// connect failed, close the channel
close();
throw SocketExceptions.of(ioe, sa);
throw Exceptions.ioException(ioe, sa);
}
}
@ -1065,7 +1065,7 @@ class SocketChannelImpl
} catch (IOException ioe) {
// connect failed, close the channel
close();
throw SocketExceptions.of(ioe, remoteAddress);
throw Exceptions.ioException(ioe, remoteAddress);
}
}
@ -1313,7 +1313,7 @@ class SocketChannelImpl
} catch (IOException ioe) {
// connect failed, close the channel
close();
throw SocketExceptions.of(ioe, sa);
throw Exceptions.ioException(ioe, sa);
}
}

View File

@ -1277,8 +1277,13 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep
#
# Enhanced exception message information
#
# By default, exception messages should not include potentially sensitive
# information such as file names, host names, or port numbers. This property
# Exception messages may include potentially sensitive information such as file
# names, host names, or port numbers. By default, socket related exceptions
# have this information restricted (meaning the sensitive details are removed).
# Exception messages relating to JAR files and exceptions containing user
# identity information are also restricted by default.
# This property can be used to relax this restriction or to place further
# restrictions on other categories, defined below. The property
# accepts one or more comma separated values, each of which represents a
# category of enhanced exception message information to enable. Values are
# case-insensitive. Leading and trailing whitespaces, surrounding each value,
@ -1291,17 +1296,28 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep
#
# The categories are:
#
# hostInfo - IOExceptions thrown by java.net.Socket and the socket types in the
# java.nio.channels package will contain enhanced exception
# message information
# hostInfo - All networking related exceptions will contain enhanced
# exception message information.
#
# hostInfoExclSocket - The hostInfo category defined above, excluding
# IOExceptions thrown by java.net.Socket and the NetworkChannel
# types in the java.nio.channels package, will contain enhanced
# exception message information
#
# jar - enables more detailed information in the IOExceptions thrown
# by classes in the java.util.jar package
#
# userInfo - enables more detailed information in exceptions which may contain
# user identity information
#
# The property setting in this file can be overridden by a system property of
# the same name, with the same syntax and possible values.
#
#jdk.includeInExceptions=hostInfo,jar
# If the property is not set or set to an empty string, then this is the most
# restricted setting with all categories disabled. The following is the default
# (out of the box) setting, meaning these categories are not restricted.
#
jdk.includeInExceptions=hostInfoExclSocket
#
# Disabled mechanisms for the Simple Authentication and Security Layer (SASL)

View File

@ -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
@ -86,9 +86,36 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
/* check if SO_REUSEPORT is supported on this platform */
REUSEPORT_available = reuseport_supported(IPv6_available);
return JNI_VERSION_1_2;
}
static int enhancedExceptionsInitialized = 0;
static int enhancedExceptionsAllowed = -1;
#define CHECK_NULL_THROW_ERROR(X) \
if (X == NULL) { \
JNU_ThrowByName(env, "java/lang/InternalError", \
"can't initialize enhanced exceptions"); \
return -1; \
}
int getEnhancedExceptionsAllowed(JNIEnv *env) {
jclass cls;
jfieldID fid;
if (enhancedExceptionsInitialized) {
return enhancedExceptionsAllowed;
}
cls = (*env)->FindClass(env, "jdk/internal/util/Exceptions");
CHECK_NULL_THROW_ERROR(cls);
fid = (*env)->GetStaticFieldID(env, cls, "enhancedNonSocketExceptionText", "Z");
CHECK_NULL_THROW_ERROR(fid);
enhancedExceptionsAllowed = (*env)->GetStaticBooleanField(env, cls, fid);
enhancedExceptionsInitialized = 1;
return enhancedExceptionsAllowed;
}
static int initialized = 0;
JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -183,4 +183,6 @@ int lookupCharacteristicsToAddressFamily(int characteristics);
int addressesInSystemOrder(int characteristics);
int getEnhancedExceptionsAllowed(JNIEnv *env);
#endif /* NET_UTILS_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -32,9 +32,10 @@ import java.util.concurrent.*;
import java.io.IOException;
import java.io.FileDescriptor;
import jdk.internal.util.Exceptions;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.util.SocketExceptions;
/**
* Unix implementation of AsynchronousSocketChannel
@ -264,7 +265,7 @@ class UnixAsynchronousSocketChannelImpl
if (e != null) {
if (e instanceof IOException) {
var isa = (InetSocketAddress)pendingRemote;
e = SocketExceptions.of((IOException)e, isa);
e = Exceptions.ioException((IOException)e, isa);
}
// close channel if connection cannot be established
try {
@ -355,7 +356,7 @@ class UnixAsynchronousSocketChannelImpl
// close channel if connect fails
if (e != null) {
if (e instanceof IOException) {
e = SocketExceptions.of((IOException)e, isa);
e = Exceptions.ioException((IOException)e, isa);
}
try {
close();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -29,6 +29,9 @@ import java.nio.file.attribute.*;
import java.io.IOException;
import static sun.nio.fs.UnixNativeDispatcher.*;
import static jdk.internal.util.Exceptions.filterUserName;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* Unix implementation of java.nio.file.attribute.UserPrincipal
*/
@ -132,18 +135,19 @@ public class UnixUserPrincipals {
private static int lookupName(String name, boolean isGroup)
throws IOException
{
int id;
int id = -1;
try {
id = (isGroup) ? getgrnam(name) : getpwnam(name);
} catch (UnixException x) {
throw new IOException(name + ": " + x.errorString());
throw new IOException(formatMsg("%s " + x.errorString(),
filterUserName(name).suffixWith(": ")));
}
if (id == -1) {
// lookup failed, allow input to be uid or gid
try {
id = Integer.parseInt(name);
} catch (NumberFormatException ignore) {
throw new UserPrincipalNotFoundException(name);
throw new UserPrincipalNotFoundException(formatMsg("%s", filterUserName(name)));
}
}
return id;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -184,16 +184,28 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
{
int size;
char *buf;
const char *format = "%s: %s";
const char *error_string = gai_strerror(gai_error);
if (error_string == NULL)
error_string = "unknown error";
int enhancedExceptions = getEnhancedExceptionsAllowed(env);
if (enhancedExceptions) {
size = strlen(hostname);
} else {
size = 0;
}
size += strlen(error_string) + 3;
size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
buf = (char *) malloc(size);
if (buf) {
jstring s;
snprintf(buf, size, format, hostname, error_string);
int n;
if (enhancedExceptions) {
n = snprintf(buf, size, "%s: %s", hostname, error_string);
} else {
n = snprintf(buf, size, " %s", error_string);
}
if (n >= 0) {
s = JNU_NewStringPlatform(env, buf);
if (s != NULL) {
jobject x = JNU_NewObjectByName(env,
@ -202,6 +214,7 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
if (x != NULL)
(*env)->Throw(env, x);
}
}
free(buf);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -33,9 +33,9 @@ import java.nio.BufferOverflowException;
import java.net.*;
import java.util.concurrent.*;
import java.io.IOException;
import jdk.internal.util.Exceptions;
import jdk.internal.invoke.MhUtil;
import jdk.internal.misc.Unsafe;
import sun.net.util.SocketExceptions;
/**
* Windows implementation of AsynchronousSocketChannel using overlapped I/O.
@ -253,7 +253,7 @@ class WindowsAsynchronousSocketChannelImpl
if (exc != null) {
closeChannel();
exc = SocketExceptions.of(toIOException(exc), remote);
exc = Exceptions.ioException(toIOException(exc), remote);
result.setFailure(exc);
}
Invoker.invoke(result);
@ -280,7 +280,7 @@ class WindowsAsynchronousSocketChannelImpl
if (exc != null) {
closeChannel();
IOException ee = toIOException(exc);
ee = SocketExceptions.of(ee, remote);
ee = Exceptions.ioException(ee, remote);
result.setFailure(ee);
}
@ -296,12 +296,12 @@ class WindowsAsynchronousSocketChannelImpl
*/
@Override
public void failed(int error, IOException x) {
x = SocketExceptions.of(x, remote);
x = Exceptions.ioException(x, remote);
if (isOpen()) {
closeChannel();
result.setFailure(x);
} else {
x = SocketExceptions.of(new AsynchronousCloseException(), remote);
x = Exceptions.ioException(new AsynchronousCloseException(), remote);
result.setFailure(x);
}
Invoker.invoke(result);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -33,6 +33,8 @@ import jdk.internal.misc.Unsafe;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;
import static jdk.internal.util.Exceptions.filterUserName;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* A SecurityDescriptor for use when setting a file's ACL or creating a file
@ -136,8 +138,8 @@ class WindowsSecurityDescriptor {
Math.max(SIZEOF_ACCESS_ALLOWED_ACE, SIZEOF_ACCESS_DENIED_ACE);
} catch (WindowsException x) {
throw new IOException("Failed to get SID for " + user.getName()
+ ": " + x.errorString());
throw new IOException(formatMsg("Failed to get SID %s : " + x.errorString(),
filterUserName(user.getName()).prefixWith("for ")));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -29,6 +29,8 @@ import java.io.IOException;
import static sun.nio.fs.WindowsConstants.*;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static jdk.internal.util.Exceptions.formatMsg;
import static jdk.internal.util.Exceptions.filterUserName;
class WindowsUserPrincipals {
private WindowsUserPrincipals() { }
@ -132,13 +134,14 @@ class WindowsUserPrincipals {
static UserPrincipal lookup(String name) throws IOException {
// invoke LookupAccountName to get buffer size needed for SID
int size;
int size = 0;
try {
size = LookupAccountName(name, 0L, 0);
} catch (WindowsException x) {
if (x.lastError() == ERROR_NONE_MAPPED)
throw new UserPrincipalNotFoundException(name);
throw new IOException(name + ": " + x.errorString());
throw new IOException(formatMsg("%s " + x.errorString(),
filterUserName(name).suffixWith(": ")));
}
assert size > 0;
@ -153,7 +156,8 @@ class WindowsUserPrincipals {
// return user principal
return fromSid(sidBuffer.address());
} catch (WindowsException x) {
throw new IOException(name + ": " + x.errorString());
throw new IOException(formatMsg("%s " + x.errorString(),
filterUserName(name).suffixWith(": ")));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
@ -88,8 +88,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) {
// report error
NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException",
hostname);
NET_ThrowByNameWithLastError(
env, "java/net/UnknownHostException",
getEnhancedExceptionsAllowed(env) ? hostname : "");
goto cleanupAndReturn;
} else {
int i = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
@ -84,7 +84,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) {
// report error
NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException",
hostname);
getEnhancedExceptionsAllowed(env) ? hostname : "");
goto cleanupAndReturn;
} else {
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,

View File

@ -33,6 +33,8 @@ import java.util.Locale;
import java.util.StringTokenizer;
import com.sun.jndi.toolkit.url.Uri;
import com.sun.jndi.toolkit.url.UrlUtil;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/*
* Extract components of an LDAP URL.
@ -119,7 +121,8 @@ public final class LdapURL extends Uri {
@Override
protected MalformedURLException newInvalidURISchemeException(String uri) {
return new MalformedURLException("Not an LDAP URL: " + uri);
return new MalformedURLException(formatMsg("Not an LDAP URL%s",
filterNonSocketInfo(uri).prefixWith(": ")));
}
@Override

View File

@ -29,6 +29,8 @@ package com.sun.jndi.toolkit.url;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
@ -232,6 +234,12 @@ public class Uri {
}
}
private MalformedURLException newMalformedURLException(String prefix, String msg) {
return new MalformedURLException(prefix +
formatMsg(filterNonSocketInfo(msg)
.prefixWith(prefix.isEmpty()? "" : ": ")));
}
/*
* Parses a URI string and sets this object's fields accordingly.
* Use java.net.URI to validate the uri string syntax
@ -241,7 +249,7 @@ public class Uri {
if (!isSchemeOnly(uri)) {
URI u = new URI(uri);
scheme = u.getScheme();
if (scheme == null) throw new MalformedURLException("Invalid URI: " + uri);
if (scheme == null) throw newMalformedURLException("Invalid URI", uri);
var auth = u.getRawAuthority();
hasAuthority = auth != null;
if (hasAuthority) {
@ -253,7 +261,7 @@ public class Uri {
+ (port == -1 ? "" : (":" + port));
if (!hostport.equals(auth)) {
// throw if we have user info or regname
throw new MalformedURLException("unsupported authority: " + auth);
throw newMalformedURLException("unsupported authority", auth);
}
}
path = u.getRawPath();
@ -262,7 +270,7 @@ public class Uri {
}
if (u.getRawFragment() != null) {
if (!acceptsFragment()) {
throw new MalformedURLException("URI fragments not supported: " + uri);
throw newMalformedURLException("URI fragments not supported", uri);
}
fragment = "#" + u.getRawFragment();
}
@ -279,7 +287,7 @@ public class Uri {
path = "";
}
} catch (URISyntaxException e) {
var mue = new MalformedURLException(e.getMessage());
var mue = newMalformedURLException("", e.getMessage());
mue.initCause(e);
throw mue;
}
@ -299,11 +307,11 @@ public class Uri {
int qmark = uri.indexOf('?');
int fmark = uri.indexOf('#');
if (i < 0 || slash > 0 && i > slash || qmark > 0 && i > qmark || fmark > 0 && i > fmark) {
throw new MalformedURLException("Invalid URI: " + uri);
throw newMalformedURLException("Invalid URI", uri);
}
if (fmark > -1) {
if (!acceptsFragment()) {
throw new MalformedURLException("URI fragments not supported: " + uri);
throw newMalformedURLException("URI fragments not supported", uri);
}
}
if (i == uri.length() - 1) {
@ -349,26 +357,26 @@ public class Uri {
String f = u.getRawFragment();
String ui = u.getRawUserInfo();
if (ui != null) {
throw new MalformedURLException("user info not supported in authority: " + ui);
throw newMalformedURLException("user info not supported in authority", ui);
}
if (!"/".equals(p)) {
throw new MalformedURLException("invalid authority: " + auth);
throw newMalformedURLException("invalid authority", auth);
}
if (q != null) {
throw new MalformedURLException("invalid trailing characters in authority: ?" + q);
throw newMalformedURLException("invalid trailing characters in authority '?'", "?" + q);
}
if (f != null) {
throw new MalformedURLException("invalid trailing characters in authority: #" + f);
throw newMalformedURLException("invalid trailing characters in authority: '#'", "#" + f);
}
String hostport = (host == null ? "" : host)
+ (port == -1?"":(":" + port));
if (!auth.equals(hostport)) {
// throw if we have user info or regname
throw newMalformedURLException("Authority component is not server-based, " +
"or contains user info. Unsupported authority: " + auth);
"or contains user info. Unsupported authority", auth);
}
} catch (URISyntaxException e) {
var mue = new MalformedURLException(e.getMessage());
var mue = newMalformedURLException("", e.getMessage());
mue.initCause(e);
throw mue;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -39,6 +39,8 @@ import static java.util.Objects.requireNonNull;
import static jdk.internal.net.http.common.Utils.isValidName;
import static jdk.internal.net.http.common.Utils.isValidValue;
import static jdk.internal.net.http.common.Utils.newIAE;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
public class HttpRequestBuilderImpl implements HttpRequest.Builder {
@ -82,7 +84,8 @@ public class HttpRequestBuilderImpl implements HttpRequest.Builder {
throw newIAE("invalid URI scheme %s", scheme);
}
if (uri.getHost() == null) {
throw newIAE("unsupported URI %s", uri);
throw new IllegalArgumentException(
formatMsg("unsupported URI %s", filterNonSocketInfo(uri.toString())));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -46,6 +46,7 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.internal.net.http.ResponseSubscribers.PathSubscriber;
import jdk.internal.util.Exceptions;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
public final class ResponseBodyHandlers {
@ -190,7 +191,12 @@ public final class ResponseBodyHandlers {
static final UncheckedIOException unchecked(ResponseInfo rinfo,
String msg) {
String s = String.format("%s in response [%d, %s]", msg, rinfo.statusCode(), rinfo.headers());
String s;
if (Exceptions.enhancedNonSocketExceptions()) {
s = String.format("%s in response [%d, %s]", msg, rinfo.statusCode(), rinfo.headers());
} else {
s = String.format("%s in response [%d]", msg, rinfo.statusCode());
}
return new UncheckedIOException(new IOException(s));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -61,6 +61,8 @@ import java.util.concurrent.CompletableFuture;
import static java.lang.String.format;
import static jdk.internal.net.http.common.Utils.isValidName;
import static jdk.internal.net.http.common.Utils.stringOf;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
public class OpeningHandshake {
@ -336,9 +338,13 @@ public class OpeningHandshake {
if (!("ws".equalsIgnoreCase(scheme) || "wss".equalsIgnoreCase(scheme)))
throw illegal("invalid URI scheme: " + scheme);
if (uri.getHost() == null)
throw illegal("URI must contain a host: " + uri);
throw new IllegalArgumentException(
formatMsg("URI must contain a host%s",
filterNonSocketInfo(uri.toString()).prefixWith(": ")));
if (uri.getFragment() != null)
throw illegal("URI must not contain a fragment: " + uri);
throw new IllegalArgumentException(
formatMsg("URI must not contain a fragment%s",
filterNonSocketInfo(uri.toString()).prefixWith(": ")));
return uri;
}

View File

@ -28,6 +28,8 @@ import java.rmi.registry.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.formatMsg;
/**
* The <code>Naming</code> class provides methods for storing and obtaining
@ -221,6 +223,11 @@ public final class Naming {
return LocateRegistry.getRegistry(parsed.host, parsed.port);
}
private static MalformedURLException newMalformedURLException(String prefix, String msg) {
return new MalformedURLException(
prefix + formatMsg(filterNonSocketInfo(msg).prefixWith(": ")));
}
/**
* Dissect Naming URL strings to obtain referenced host, port and
* object name.
@ -241,7 +248,7 @@ public final class Naming {
* Convert the authority to a localhost:<port> form
*/
MalformedURLException mue = newMalformedURLException(
"invalid URL String: " + str);
"invalid URL String", str);
mue.initCause(ex);
int indexSchemeEnd = str.indexOf(':');
int indexAuthorityBegin = str.indexOf("//:");
@ -273,21 +280,21 @@ public final class Naming {
URI uri = new URI(str);
if (uri.isOpaque()) {
throw newMalformedURLException(
"not a hierarchical URL: " + str);
"not a hierarchical URL", str);
}
if (uri.getFragment() != null) {
throw newMalformedURLException(
"invalid character, '#', in URL name: " + str);
"invalid character, '#', in URL name", str);
} else if (uri.getQuery() != null) {
throw newMalformedURLException(
"invalid character, '?', in URL name: " + str);
"invalid character, '?', in URL name", str);
} else if (uri.getUserInfo() != null) {
throw newMalformedURLException(
"invalid character, '@', in URL host: " + str);
"invalid character, '@', in URL host", str);
}
String scheme = uri.getScheme();
if (scheme != null && !scheme.equals("rmi")) {
throw new MalformedURLException("invalid URL scheme: " + str);
throw newMalformedURLException("invalid URL scheme", str);
}
String name = uri.getPath();

View File

@ -35,6 +35,8 @@ public class JWebServer {
private static final String SYS_PROP_MAX_CONNECTIONS = "jdk.httpserver.maxConnections";
private static final String DEFAULT_JWEBSERVER_MAX_CONNECTIONS = "200";
private static final String SYS_PROP_ENHANCED_EXCEP = "jdk.includeInExceptions";
private static final String DEFAULT_ENHANCED_EXCEP = "net";
/**
* This constructor should never be called.
*/
@ -61,6 +63,7 @@ public class JWebServer {
*/
public static void main(String... args) {
setMaxReqTime();
setEnhancedExceptions();
setMaxConnectionsIfNotSet();
int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true), "jwebserver", args);
@ -80,6 +83,14 @@ public class JWebServer {
}
}
static void setEnhancedExceptions() {
if (System.getProperty(SYS_PROP_ENHANCED_EXCEP) != null) {
// an explicit value has already been set, so we don't override it
return;
}
System.setProperty(SYS_PROP_ENHANCED_EXCEP, DEFAULT_ENHANCED_EXCEP);
}
static void setMaxConnectionsIfNotSet() {
if (System.getProperty(SYS_PROP_MAX_CONNECTIONS) == null) {
System.setProperty(SYS_PROP_MAX_CONNECTIONS, DEFAULT_JWEBSERVER_MAX_CONNECTIONS);

View File

@ -226,7 +226,11 @@ public class CommandLineNegativeTest {
}
static OutputAnalyzer simpleserver(String... args) throws Throwable {
var pb = new ProcessBuilder(args)
String[] nargs = new String[args.length + 1];
nargs[0] = args[0];
System.arraycopy(args, 1, nargs, 2, args.length-1);
nargs[1] = "-Djdk.includeInExceptions=hostInfo";
var pb = new ProcessBuilder(nargs)
.directory(TEST_DIR.toFile());
var outputAnalyser = ProcessTools.executeCommand(pb)
.outputTo(System.out)

View File

@ -26,6 +26,7 @@
* @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800
* 7171415 6339649 6933879 8037396 8272072 8051627 8297687 8353013
* @author Mark Reinhold
* @run main/othervm Test
*/
import java.io.ByteArrayInputStream;

View File

@ -28,7 +28,7 @@ import java.security.Security;
* @bug 8207846 8208691
* @summary Test the default setting of the jdk.net.includeInExceptions
* security property
* @comment In OpenJDK, this property is empty by default and on purpose.
* @comment In OpenJDK, this property has value "hostInfoExclSocket" by default
* This test assures the default is not changed.
* @run main TestJDKIncludeInExceptions
*/
@ -36,9 +36,9 @@ public class TestJDKIncludeInExceptions {
public static void main(String args[]) throws Exception {
String incInExc = Security.getProperty("jdk.includeInExceptions");
if (incInExc != null) {
if (incInExc == null || !incInExc.equals("hostInfoExclSocket")) {
throw new RuntimeException("Test failed: default value of " +
"jdk.includeInExceptions security property is not null: " +
"jdk.includeInExceptions security property does not have expected value: " +
incInExc);
}
}

View File

@ -0,0 +1,172 @@
/*
* 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.IOException;
import java.net.InetAddress;
import java.util.Arrays;
import jdk.internal.util.Exceptions;
import jdk.internal.util.Exceptions.SensitiveInfo;
import static jdk.internal.util.Exceptions.formatMsg;
import static jdk.internal.util.Exceptions.filterNonSocketInfo;
import static jdk.internal.util.Exceptions.enhancedNonSocketExceptions;
/*
* @test
* @bug 8348986
* @summary Improve coverage of enhanced exception messages
* @modules java.base/jdk.internal.util
* @run main/othervm -Djdk.includeInExceptions=hostInfo ExceptionsTest
* @run main/othervm ExceptionsTest
* @run main/othervm -Djdk.includeInExceptions=userInfo ExceptionsTest
* @run main/othervm -Djdk.net.hosts.file=does.not.exist -Djdk.includeInExceptions=userInfo ExceptionsTest
* @run main/othervm -Djdk.net.hosts.file=does.not.exist -Djdk.includeInExceptions=hostInfo ExceptionsTest
*/
public class ExceptionsTest {
static boolean netEnabled() {
System.out.printf("netEnabled = %b\n", enhancedNonSocketExceptions());
return enhancedNonSocketExceptions();
}
static boolean dnsEnabled() {
System.out.printf("dnsEnabled = %b\n", enhancedNonSocketExceptions());
return enhancedNonSocketExceptions();
}
static boolean hostFileEnabled() {
return System.getProperty("jdk.net.hosts.file", "").length() > 0;
}
static String[][][] tests = {
//
// If a format argument is of the form ".pre(xxx)" or ".suf(yyy)", then that is
// interpreted as a .prefixWith("xxx") or .suffixWith("yyy") call to the preceding
// argument. .rep() signifies .replaceWith()
//
// Number of elements in array
// ---------------------------
// 1 N 2
//
// Format string args to format Enhanced o/p non-enhanced o/p
//
/* 1 */ {{"foo: %s bar"}, {"abc"}, {"foo: abc bar", "foo: bar"}},
/* 2 */ {{"foo: %s bar"}, {"a", "b"}, {"foo: a bar", "foo: bar"}},
/* 3 */ {{"foo: %s bar"}, {null}, {"foo: null bar", "foo: bar"}},
/* 4 */ {{"foo: %s bar"}, {""}, {"foo: bar", "foo: bar"}},
/* 5 */ {{"%s foo: %s bar"}, {"a", "b"}, {"a foo: b bar", "foo: bar"}},
/* 6 */ {{"foo: %s bar %s"}, {"a", "b"}, {"foo: a bar b", "foo: bar"}},
/* 7 */ {{"foo: %s bar %s"}, {"abc", "def"}, {"foo: abc bar def", "foo: bar"}},
/* 8 */ {{"%s bar %s"}, {"abc", ".pre(foo: )", "def"}, {"foo: abc bar def", "bar"}},
/* 9 */ {{"%s baz"}, {"abc", ".suf(: bar)"}, {"abc: bar baz", "baz"}},
/* 10 */ {{"%s baz"}, {"abc", ".suf(: bar)"
, ".rep(bob)"}, {"abc: bar baz", "bob baz"}}
};
static void dnsTest() {
String host = "fub.z.a.bar.foo";
try {
var addr = InetAddress.getByName(host);
} catch (IOException e) {
if (!dnsEnabled() && e.toString().contains(host))
throw new RuntimeException("Name lookup failed");
}
}
static void hostFileTest() {
String result1 = "Unable to resolve host www.rte.ie as hosts file does.not.exist not found";
String result2 = "Unable to resolve host as hosts file " +
"from ${jdk.net.hosts.file} system property not found";
try {
var a = InetAddress.getByName("www.rte.ie");
} catch (IOException e) {
if (dnsEnabled() && !e.toString().contains(result1)) {
System.out.println("Lookup failed: " + e.toString());
throw new RuntimeException("Name lookup failed");
}
if (!dnsEnabled() && !e.toString().contains(result2)) {
System.out.println("Lookup failed: " + e.toString());
throw new RuntimeException("Name lookup failed");
}
}
}
final static String PRE = ".pre(";
final static String SUF = ".suf(";
final static String REP = ".rep(";
static SensitiveInfo[] getArgs(String[] args) {
SensitiveInfo[] sa = new SensitiveInfo[args.length];
int index = 0;
for (String s : args) {
if (s != null && s.startsWith(PRE)) {
var preArg = s.substring(PRE.length(), s.indexOf(')'));
sa[index-1] = sa[index-1].prefixWith(preArg);
} else if (s != null && s.startsWith(SUF)) {
var sufArg = s.substring(SUF.length(), s.indexOf(')'));
sa[index-1] = sa[index-1].suffixWith(sufArg);
} else if (s != null && s.startsWith(REP)) {
var repArg = s.substring(REP.length(), s.indexOf(')'));
sa[index-1] = sa[index-1].replaceWith(repArg);
} else {
sa[index++] = filterNonSocketInfo(s);
}
}
return Arrays.copyOf(sa, index);
}
public static void main(String[] a) {
if (!hostFileEnabled()) {
dnsTest();
} else {
hostFileTest();
return;
}
int count = 1;
for (String[][] test : tests) {
String format = test[0][0];
String expectedEnhanced = test[2][0];
String expectedNormal = test[2][1];
SensitiveInfo[] args = getArgs(test[1]);
String output = formatMsg(format, args);
if (netEnabled()) {
if (!output.equals(expectedEnhanced)) {
var msg = String.format("FAIL %d: got: \"%s\" Expected: \"%s\"", count,
output, expectedEnhanced);
throw new RuntimeException(msg);
}
} else {
if (!output.equals(expectedNormal)) {
var msg = String.format("FAIL %d: got: \"%s\" Expected: \"%s\"", count,
output, expectedNormal);
throw new RuntimeException(msg);
}
}
count++;
}
}
}