且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

velocity 区间运算符导致生产环境OOM

更新时间:2022-08-25 18:17:11

最近生产环境某些机器频繁出现FullGC和OOM,用jmap的heap功能查看该Java进程的内存使用情况,如下图:

velocity 区间运算符导致生产环境OOM


问题分析:


再用jmap的histo图查看当前对象分布图,发现有很多Integer(为啥?不知道啊。。。下面分解)

velocity 区间运算符导致生产环境OOM

这里可以很明显看到,光Integer就占用了1G多内存空间。


手工dump一台的机器,jmap –dump:format=b,file=/home/admin/logs/aaa.bin –F<pid>


这里将持续很久,而且可能报错抛异常 UnmappedAddressException,一旦抛出

这种异常,就需要再次重试。另外注意磁盘空间必须保持充足(剩余空间至少是物理内存1.5倍)。


使用MAT工具,分析dump结果。


观察出问题的线程,如下图

velocity 区间运算符导致生产环境OOM

还有其heap占用情况:

velocity 区间运算符导致生产环境OOM


可以观察到,该线程持有一个3G空间大小的Integer数组,刚好印证了之前的histo图。

那这么大的一个int数组从哪来就很值得怀疑。查看ASTIntegerRange类的源码的140行,如下图:


velocity 区间运算符导致生产环境OOM


至此,大概可以确定,问题应该就出在这。

关键在于,这个类是Velocity自己的类,我们对此一无所闻,它在哪里被调用,被谁调用,也无法知道。

查看Apache官方文档,找到蛛丝马迹,该类是用来处理[n..m]这种运算符的。


搜了一下整个代码里面,只有一个地方用到了该语法:

velocity 区间运算符导致生产环境OOM


这里的endIndex,是后台根据总页数直接计算出来的,攻击者没法伪造。

但是startIndex则是根据用户传入的当前页数来决定的。

而且最关键的一点,该语法既可以是单调增,也可以是单调减(比如[1 .. 100]或者[100 .. 1])


因而,一旦用户传入一个很大的当前页数值,velocity会在内部构建一个大小为|n-m|的ArrayList(它内部实际上就是数组)

从而导致OOM。










本文转自 kevx 51CTO博客,原文链接:http://blog.51cto.com/spinlock/1315202,如需转载请自行联系原作者