【背景】
同一脚本,剧情发展,点击链接跳转查看:
表面看来是这个原因(下图,截图自上文3),最后分析完发现真相差得有点远……
【排查过程】
STEP1、缺陷暴露与初步观察
读取1000kb以上文件发送报文,接口返回“解密异常”,初步怀疑发出去的密文不完整导致,首先想到的是文件太大。于是试了一个136bk大小的密文读取发送,可以成功提交。又试了一个137kb大小的密文发送,返回“解密异常”。
试了其他几份136kb与137kb的文件都是一样的情况,136kb提交成功,137kb返回解密异常,推测136kb/137kb之间存在一个过度值。难道是字符指针变量大小存在某种限制?可是在网上搜索了一下,不管是136kb还是137kb在计算机领域来说并不是一个有特殊意义的值……
当然最大的前提就是这些136kb和137kb的文件如果通过soapUI发出都能正常提交成功,排除文件本身原因。
STEP2、将缺陷定位至自定义函数testfn()
在Action()中将用于存放读取文件后的字符指针变量打印出来,返回为“解密异常”的报文,提交时确实漏了最后一部分数据内容。
需要确定是否在文件读取时就没有将这部分内容读进来,于是在自定义函数testfn()中输出读取的文本长度与文本内容。
结果确实是读取的时候就已经丢失了后面部分的内容。这样就将返回缩小到了自定义函数,即便真的是变量或者内存大小的问题,也只发生在该区域内。
STEP3、将缺陷定位至fread函数
考虑到136kb这个值没有什么特殊意义,大胆推测下这个137kb的限制只是一个巧合。最终通过以下两项尝试验证了这个假设:
①另找一份500kb文件断读处已大于137kb;
②扩大字符指针的内存大小(原始设定为文件大小),未能因此将多余的1kb读进;
再将目光转向用于文件读取的fread函数,先看下函数结构:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
fread(buffer, sizeof(char), filelenth, file_stream);
buffer是读取内容存放指针;size是每次读取大小,这里的值是sizeof(char),即为1;count是读取次数,沿用了之前的文件大小变量filelenth;stream是要读取得文件指针,使用了前文定义的文件开始位置值file_stream。
给函数赋值的变量取值似乎没什么问题,假设是这个函数本身有问题。在网上查询这个函数资料时,不难了解到一种评论“fread可以读二进制文件,有时用字符方式去读文件不能读完整个文件,但是二进制方式就可以”,可以说看到这里就是柳暗花明了……
STEP4、缺陷修复
系统系统默认文件结束符为ctrl+z,其ASCII值为“0x1A”,fread函数遇到这个字符串时自动结束文件读取。回头看看那些文件中断点,やっぱり!
改成以二进制读取即可避免这个问题
file_stream = fopen(filename, "r")改成
file_stream = fopen(filename, "rb")
r是以只读方式打开,rb是以二进制只读方式打开。换成rb后果然没毛病了,一口气读1MB不喘气,yooooo~~~
我真是个机智的狗儿~
【结语】
如果我对fread函数有足够的了解,可能一眼就能看出症结所在,不过现在这样也好,从实践反推理论和,记忆深刻……
这个脚本前后陆续撸了快一周了,到这个bug修复差不多应该结束了,跟出连续剧似的……
↓↓扫一扫,防脱发↓↓