NegativeArraySizeException 根源是非法负长度内存分配,须在解析阶段校验 length >= 0;getLength() 返回 -1 应流式读取;字节序、符号位、整数溢出均需防范,关键计算用 long 防溢出。

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










