前段时间,FastJson被挖出来一个漏洞,可能导致服务直接瘫痪,这个问题就严重,搞的人心惶惶,半夜拼命升级,就怕飞来横锅。

我也是很好奇,一个序列化工具那么大能耐,可以直接把服务弄瘫痪?

本着好奇心,先看下最新版本是怎么修复的,上FastJson的github的官网,找到对应的commiter记录,很好找。




java fastjson 怎么解析json 带数字key_Java


就是它了,点进去可以看到具体的代码差异


java fastjson 怎么解析json 带数字key_JSON_02


原来这个处理方案很暴力,直接加一层过滤,如果字符串包含x,就甩一个异常到你脸上。

那就在本地写一个demo,看看能不能复现,本地用的是1.2.58


java fastjson 怎么解析json 带数字key_JSON_03


设置-Xmx4G,开始运行,过了一两秒,果然甩了我一个OOM


java fastjson 怎么解析json 带数字key_fastjson 循环json字符串_04


既然复现了,那就debug下哪里出了问题,根据修复代码,我们在JSONLexerbase类的ScanString方法的switch分支中的case 'x' 打个断点。


java fastjson 怎么解析json 带数字key_Java_05


开始debug,进来之后,进入第一个next方法


java fastjson 怎么解析json 带数字key_Java_06


next方法会对bp进行+1操作并赋给index,如果index>=this.len(JSON的长度)就会返回'',表示已经读完,否则返回文本内容。

在我们这个例子中,执行完第一个next,index的值已经等于JSON字符串的长度,所以返回了''

执行 charx2=this.next()的时候,index等于9,大于JSON字符串长度,也返回''

继续执行这个case分支的最后一行 this.putChar(x_char)


java fastjson 怎么解析json 带数字key_fastjson 循环json字符串_07


这个方法中,会对sp和sbuf.length(默认是512)进行比较,如果达到了,就进行扩容,可以猜到这里可能是OOM的元凶,不断的进行扩容,把内存耗尽。

继续往下执行,返回到了scanString方法,在while循环中,执行next方法,因为index值肯定大于JSON字符串长度,所以会返回''


java fastjson 怎么解析json 带数字key_Java_08


接下去会返回的字符ch,如果是'',会执行 putChar方法(该方法在上面截图中有显示),执行完sp的值+1,然后继续执行,又返回scanString方法,又开始了一轮。

最终sp会涨到512,这个时候,进入if分支,开始扩容。

噩梦就这么开始了...

还没升级到最新版 1.2.60 的小伙伴,抓紧哦。