Java 的 stdlib SocksSocketImpl 中的错误?

问题描述 投票:0回答:1

我注意到我的一个 Spring Boot 应用程序在嵌入式 Tomcat 关闭过程中通过

URISyntaxException
出现了一种特殊的抑制
TomcatWebServer#stop()
- 经过调试,发现源代码在这里:

https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/net/SocksSocketImpl.java#L306

(这发生在我的 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)
    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
需要一个 非编码 IPv6 地址 带有必需的文字大括号,即
[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

我认为拥有

host == null
稍后会导致 SocksSocketImpl 崩溃,但是,令人惊讶的是,在唯一真正使用
uri
的地方,即对
DefaultProxySelector#select(URI uri)
的调用,我发现了一个不相关的解决方法...所描述的明确表示不适用于本例,但允许代码不会失败! https://github.com/openjdk/jdk/blob/jdk-10%2B24/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java#L168(即,此代码 在正常情况下实际上会崩溃,如果不是因为几十年前的黑客解决方法 对于完全不相关的情况 - 国际域名和带下划线的域名)。

我是否遗漏了一些明显的东西,或者它是 stdlib 本身的堆积错误(因此应该向上游报告)?

java spring-boot uri ipv6
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.