在通过TomcatWebServer#stop()
进行嵌入式Tomcat关机过程中,我注意到我的一个Spring Boot应用程序中有一个特殊的URISyntaxException
被 suppress --在调试后,我发现源代码是这样的:
(这发生在我的Eclipse Temurin 17.0.8.1上,但我try 了其他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)
对host
到%5bfd00:baba:babe:0:0:0:0:862%5d
进行编码-这是有问题的,因为稍后通过URI解析将无法区分主机名和端口,但本身不应该导致异常 - 然后将其与模式/端口连接并给出例如
socket://%5fd00:baba:babe:0:0:0:0:862%5d:55507
-甚至更多的问题,因为现在它对人眼和可能对new URI
输入解析器来说都看起来更麻烦, - 然而,
new URI
c-tor构造了一个URI,其编码的主机名和端口聚集在一起,分别为authority
、host == null
和port == -1
为了对基于IPv6的主机正常工作,new URI
期望non-encoded IPv6地址with required literal braces,即[fd00:baba:babe:0:0:0:0:862]
,
简单的复制 case :
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
我认为拥有host == null
应该会在以后导致SocksSocketImpl崩溃,但令人惊讶的是,在唯一实际使用uri
的地方,即调用DefaultProxySelector#select(URI uri)
时,我发现了一个无关的解决方法……这被明确描述为not for this case,但允许代码不会失败!https://github.com/openjdk/jdk/blob/jdk-10%2B24/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java#L168(即,如果不是几十年前的黑客解决办法for completely unrelated cases-国际域名和带下划线的域名,则此代码would实际上在正常情况下崩溃).
我是否遗漏了一些明显的东西,或者它是stdlib本身中的堆叠错误(因此应该向upstream 报告)?