NegativeArraySizeException 根源是非法负长度内存分配,须在解析阶段校验 length >= 0;getLength() 返回 -1 应流式读取;字节序、符号位、整数溢出均需防范,关键计算用 long 防溢出。
遇到
,往往不是数组本身“写错了”,而是上游数据(比如网络响应头里的
)被误读、截断或未校验,导致用负数去申请内存——这本质是非法内存分配风险,必须在解析阶段就拦截。
网络长度字段解析必须做非负校验
HTTP 响应中
可能返回
(表示长度未知),直接用于
就会崩溃。这不是逻辑错误,而是协议兼容性疏忽。
永远不要跳过判断
:哪怕文档说“该字段必填”,也要按实际返回值处理
若
返回
,说明服务端未设置
或使用了分块传输(chunked),此时应改用流式读取(如
循环 + 动态扩容
)
避免把字符串长度解析错位:例如从响应体前几字节解析自定义包头中的 length 字段时,注意字节序(big-endian 还是 little-endian)、是否带符号(
vs
)
防止整数溢出导致隐性负值
当长度由多个字段计算得出(如 “总长 = 头部长度 + 内容长度 + 校验长度”),int 类型易因溢出变负,尤其在处理大文件或恶意构造报文时。
关键计算步骤优先用
进行中间运算,再检查是否超出
示例:
→
不依赖 JVM 默认溢出行为(Java 不抛异常,而是静默回绕),必须主动防御
外部输入一律视为不可信,强制兜底策略
无论长度来自 HTTP header、自定义二进制协议头、还是配置项,只要参与
,就必须有明确的容错路径。
校验失败时,不建议静默设为
(可能掩盖问题),而应抛出带上下文的
或
,例如:
对调试友好的做法:记录原始 raw length 值、来源字段名、当前线程与请求 ID,便于快速定位是服务端 bug 还是中间设备篡改
生产环境可加熔断:连续 N 次收到非法 length,自动降级为安全模式(如限制最大申请 1MB,拒绝超长包)
真正安全的内存申请,不在
那一行,而在它前面三步的数据清洗、类型防护和边界判定。一次没校验的
,可能就是 RCE 的入口点。
NegativeArraySizeExceptionContent-Lengthconnection.getLength()-1new byte[length]length >= 0getLength()-1Content-Lengthread()ByteArrayOutputStreamintunsigned intlongInteger.MAX_VALUElong total = (long)headerLen + contentLen + checksumLen;if (total > Integer.MAX_VALUE || total new byte[...]0IOExceptionIllegalArgumentException"Invalid Content-Length: -128, remote host may be compromised"newlength