提问人:user213769 提问时间:10/12/2023 最后编辑:user213769 更新时间:11/3/2023 访问量:103
Java 的 stdlib SocksSocketImpl 中的错误?
a bug in Java's stdlib SocksSocketImpl?
问:
我注意到在嵌入式 Tomcat 关闭过程中,我的一个 Spring Boot 应用程序中有一个特殊的抑制 - 调试后,发现源在这里:URISyntaxException
TomcatWebServer#stop()
(这在 Eclipse Temurin 17.0.8.1 上发生在我身上,但我尝试使用其他 Java 版本,它看起来基本相同)
基本上,无论我多么努力地盯着它看,对于IPv6(我的用例),这段代码看起来都坏了。
epoint.getHostString()
给出有效的 IPv6,不带大括号(例如fd00:baba:babe:0:0:0:0:862
)- 以下代码检测 IPv6 并添加大括号,
epoint
[fd00:baba:babe:0:0:0:0:862]
ParseUtil.encodePath(host)
将其编码为 - 这是有问题的,因为主机名和端口以后无法通过 URI 解析来区分,但本身不应该导致异常host
%5bfd00:baba:babe:0:0:0:0:862%5d
- 然后将其与模式/端口连接起来,并给出例如 - 更成问题的是,因为现在它看起来对人眼和输入解析器来说都更加烦恼,
socket://%5fd00:baba:babe:0:0:0:0:862%5d:55507
new URI
- 但是,c-tor 构造一个 URI,其中编码的主机名和端口聚集在一起,为 、 和 和
new URI
authority
host == null
port == -1
要在基于 IPv6 的主机上正常工作,需要具有所需文本大括号的未编码 IPv6 地址,即new URI
[fd00:baba:babe:0:0:0:0:862]
简单复制案例:
URI uri = new URI("socket://[fd00:baba:babe:0:0:0:0:862]:55507");
System.out.println(uri.getHost()); // [fd00:a89f:8b41:0:0:0:0:862] - OK
uri = new URI("socket://%5fd00:baba:babe:0:0:0:0:862%5d:55507");
System.out.println(uri.getHost()); // null - port is -1, everything got clumped in authority
uri = new URI("socket://fd00:baba:babe:0:0:0:0:862:55507");
System.out.println(uri.getHost()); // null - port is -1, everything got clumped in authority
我以为以后应该会使 SocksSocketImpl 崩溃,但是,令人惊讶的是,在唯一真正使用的地方,即调用 ,我发现了一个不相关的解决方法......这被明确描述为不适用于这种情况,但允许代码不会失败!https://github.com/openjdk/jdk/blob/jdk-10%2B24/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java#L168(也就是说,如果不是针对完全不相关的情况(国际域名和带下划线的域名)的几十年前的黑客解决方法,此代码实际上会在正常情况下崩溃)。host == null
uri
DefaultProxySelector#select(URI uri)
我是否遗漏了一些明显的东西,或者它是 stdlib 本身的堆积错误(因此应该向上游报告)?
答:
验证为错误并报告为 https://bugs.java.com/bugdatabase/view_bug?bug_id=JDK-8318130 - 通过 https://github.com/openjdk/jdk/pull/16265/files 在 JDK 22 b21 中修复
评论