跳转到主内容
极星编程网:以代码为星,赴技术山海!

NegativeArraySizeException 防御:分析在解析网络数据包长度变量时防止非法内存申请的校验

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)、是否带符号(
int
vs
unsigned 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 的入口点。

相关文章