AS3处理GB2312数据的严重BUG

BUG描述:

flash as3使用URLLoader & URLRequest加载gb2312文本时,字符串内存边界判断有误,导致读出的数据结尾有随机乱码或者数据读取不完整。

捉虫全记录:

> 使用as3加载解析XML时,发现偶尔会抛出XML格式错误的异常,运气不好的话出现频率非常之高;

> 用trace显示数据内容时,发现文件有时加载不全、有时尾部有随机乱码;

> 使用抓包软件发现数据完全正常,所以肯定是flash搞的鬼;

> 开始怀疑文本编码导致的问题,将文件存为utf-8后,完全没问题;

> 试了多次,随机内容有时完全是无关的东东,偶尔还有其它进程里的一些数据;

> 到此为止,可以肯定是内存字符串结束符处理问题;

影响面:

flashplayer 9, 10

解决方案:

方案一: 尽量不要使用gb2312数据源,如果非用不可,可参考《方案二》;

方案二: 建立socket连接,自已发送http header,接收数据进行解析,如果遇到跨域问题则看《方案三》;

方案三: 在数据尾部加入特殊的结束符(比如:),数据加载完成后把结束符后的内容全部去掉,如果遇到加载不完整的情况,则重试加载(记得要限制次数),不能100%保证,经过测试重试后成功率99.9%;

附件:

BUG演示程序

 

根据allen的处理方法,进一步追查了原因,可以确切的定位出是ByteArray.toString方法的BUG所致:

> URLLoader.data 是 ByteArray 类型,所以只要把 e.target.data as String 改为 e.target.data.readMultiByte(e.target.data.length, "gb2312") 即可以解决问题;

> e.target.data as String 实际上是执行了 ByteArray 的 toString 方法,那么很可能BUG是出在 ByteArray.toString 方法;

> ByteArray相当于是向量数组,length值应该是根据写入数据长度来改变,所以length值无论如何都是正确的,所以按上面 readMultiByte 方法读取,不会读出多余的数据,而 ByteArray.toString 方法并不能使用属性length来获取数据长度,需要根据编码类型来动态计算,正常来说是不会有错的,错就错在处理部分编码类型时使用了strlen或sizeof去获取数据长度,而ByteArray是可以存任何二进制数据的,当然不会有\0结束,这样的情形下strlen和sizeof是绝对不可信赖的;

> 只有这样才能解释 toString 的BUG。
 
结论是:
不要尝试使用 ByteArray.toString 的方法来获取 gb 编码的数据,最好是根据目标编码,使用 readMultiByte 读取。

No Comment

Comments are closed.