Netty 4.2.20.Final(2026-11-02,同日还有 4.1.140.Final)里有一处很实在的行为变化:宽松路径下的 HttpVersion.valueOf / 宽松构造,遇到装不进 int 的主次版本数字,以前会静默乘法溢出,吐出一个「看起来合法、其实已经算错」的版本对象;现在直接抛 IllegalArgumentException。Spring Boot 4.1.2 默认仍是 4.2.19.Final,要显式抬 netty.version 才能带上。
许可证 Apache-2.0。仓库 netty/netty。主源见 4.2.20.Final 官博、GitHub Release,对应改动 #17836(4.1 线自动移植 #17859)。
场景
网关、代理、自定义 HTTP 编解码偶尔会把请求行或探测串交给 Netty 的 HttpVersion 解析。宽松模式本来允许非标准协议名,也允许多位数字。问题在于:位数一长,内部用未检查的乘法往 int 里塞,溢出去了也不报错。
官方 PR 举的例子就是 HttpVersion.valueOf("H/9999999999.1")。旧版 text() 会变成 H/1410065407.1,主版本已经不是输入里的那个数。后续若拿 majorVersion() 做分支、限流或协议协商,等于在错版本上往下走。严格解析本来只接受单位数字,不受影响;中招的是 valueOf(String) 和宽松构造。
4.2.20 / 4.1.140 起,装不进 int 的版本数字按非法版本处理,和其他非法输入一样抛 IllegalArgumentException。fuzz 发现后修的。
Boot 4.1.2 双版本对照
同一台机器、JDK 21.0.12.1、Spring Boot 4.1.2。BOM 里 netty.version 默认 4.2.19.Final。两个独立进程,只改这一属性,其余代码相同:启动后打印 jar,再解析同一串输入。
String raw = "H/9999999999.1";
try {
HttpVersion parsed = HttpVersion.valueOf(raw);
System.out.println("PARSE_OK text=" + parsed.text());
System.out.println("PARSE_OK major=" + parsed.majorVersion()
+ " minor=" + parsed.minorVersion());
} catch (IllegalArgumentException e) {
System.out.println("PARSE_FAIL type=" + e.getClass().getName());
System.out.println("PARSE_FAIL message=" + e.getMessage());
}
父 POM 用 Boot 4.1.2,再显式依赖 netty-codec-http(版本跟 BOM)。对照时分别钉:
<properties>
<netty.version>4.2.19.Final</netty.version>
<!-- 或 4.2.20.Final -->
</properties>
4.2.19(摘录):
:: Spring Boot :: (v4.1.2)
NETTY_HTTP_VERSION=4.2.19.Final
NETTY_CODEC_HTTP_JAR=file:/.../netty-codec-http-4.2.19.Final.jar
INPUT=H/9999999999.1
PARSE_OK text=H/1410065407.1
PARSE_OK major=1410065407 minor=1
PARSE_OK protocolName=H
4.2.20(摘录):
:: Spring Boot :: (v4.1.2)
NETTY_HTTP_VERSION=4.2.20.Final
NETTY_CODEC_HTTP_JAR=file:/.../netty-codec-http-4.2.20.Final.jar
INPUT=H/9999999999.1
PARSE_FAIL type=java.lang.IllegalArgumentException
PARSE_FAIL message=Invalid version number, too large: H/9999999999.1
同一输入,旧版「解析成功」但主版本已是溢出后的 1410065407;新版直接失败,消息写明 too large。正常的 HTTP/1.1、HTTP/2.0 不受影响。
升级时注意
Boot 4.1.2 不会自动带到 4.2.20,在属性里改 netty.version,或等后续 Boot 抬默认值。走 4.1 线的项目对应升 4.1.140.Final。抬完再跑一遍依赖树,确认 netty-codec-http 等模块版本一致。
若业务自己吞掉了 IllegalArgumentException,或者把任意探测串塞进 HttpVersion.valueOf,升级后会从「错版本继续跑」变成「解析失败」。这是预期收紧,按失败路径处理即可。
同日公告还列了多条安全修复(含若干 GHSA)。安全面总览可对照站内旧文 Netty 4.2.19 / 4.1.139 安全修复;本稿只盯 HttpVersion 这一处可对照的行为变化,不叠写整包 advisory。
一起交流
分享你的思考,让讨论更进一步。