用户可输入测试字符集共享

2011-02-24  吕艳菊 

别人写的一篇文章,很实用.比较长,请耐心~~
                                       
字符是社区类产品测试的一个难点,除了各种字符编码方式的差异性外,千奇百怪的用户也总会给我们很多“惊喜”。下文是我在贴吧和passport产品线测试中关于字符测试的一些经验积累,供大家参考。很多case和分类都是不断总结和积累下来的,我所列出的肯定不是最完整的,还需要大家一起不断的补充和积累。更多case请参考wiki原文。
实际上,在总结中,我也觉得测试中要做到面面俱到非常困难,消除潜在危机的最好办法就是尽可能深入的了解每处字符处理的细节,另外推动字符处理方式的标准化也很急迫。
对于用户可以输入的字符框,我们要分别考虑如下字符类型的测试:
A.   英文,重点注意大小写转换方面的case
B.   数字,通常情况下需要考虑的特殊数字包括:
1,   0,尤其是以0开头或结尾的数字或者字符组合。经典case例如:
1)   Passport曾经有个版本处理以0开头的用户名异常,导致该类用户名无法登陆,原因是识别用户名时会用到\0,代码处理不周密;
2)   某些函数可能会把某个数值做为除数(例如qsort),导致算术错误。
2,   -1,1,
贴吧pb模块曾经在当前day库里的cur_status里为1时,重启模块丢失数据;
3,   65536,65535,-65536,-65535;
这些处于边界值的数字可能存在潜在得编码转换或者数学处理问题
4,   小数,分数等
C.   汉字,这部分重点测试与GBK编码相关的输入:
1,   GBK编码中和其他编码方式产生重叠或关联的字符如GBK字符会与UTF-8产生交集的问题,参考附件《GBK编码和UTF-8编码的交集.doc》以及附录。
2,   GBK编码中和其他编码方式有冲突或者有处理方式不一样的个别字符,例如GB18030相对GBK增加的字符,这种字符很不常用,容易被忽略;
3,   gbk编码有%5C等和\编码一样的汉字,例如賊编码为%D9%5C,这里的%5C容易被误理解为\符号
4,   部分模块可能会对两个相邻汉字处理异常导致。例如:贴吧内容过滤模块confilter模块曾经将汉字“哈布”相连的2个字节被识别为“妓”,正好是个过滤词,导致正常帖子被过滤
5,   半个汉字问题,多半出现在大段字符串被截断的情况,或者输入法进行了全角半角切换输入。
D.   全角和半角标点,重点测试 /,\,<>,!,$,&,;,_,%,*等这些键盘可直接输入的字符,以及可以作为计算机语言关键字的字符:
1,   用户输入如果可能被保留在url里时,需要注意 & / = 等可以被作为url关键字的符号
2,   可以构成强制转义字符的字符集,例如&#30911; &#
3,   可能被程序转义成为其他字符的标点,例如',参考附录4
4,   有可能被作为数据结构分隔符的字符
例如贴吧pb模块曾经将 ^!作为变长数据分隔符
5,   可能被隐藏在页面内的字符,例如 !##^&^*&^*&*^#*$&*~_&!~^*~@#&@^%#(~@)#&
E.   全角和半角字符
1,   输入法可以输入的字符,例如▲★【】『┰┯┾§』
2,   带€的用户名,参考附录7
3,   大于ascii128编码的字符,例如ó,参考附录4;
4,   有可能被作为分隔符的标点 :,;、(全半角均可)
5,   在html文本格式下和在纯文本格式下显示不一样的字符,这方面的处理异常多出现邮件正文中,例如“被处理转义为à”
F.   日文字符(ハノヌソタチッ)
日文字符编码和其他小语种编码不太一致,需要专门设计case,例如贴吧的主题列表页和帖子内容页对于日文字符的处理是一致的,但是对于韩文,主题列表页标题显示为韩语字符对应的ASCII码,进入帖子内容后才显示韩语字符。
G.   韩语和其他少数语种
例如在贴吧,韩文和其他少数语种,主题列表页标题显示为韩语字符对应的ASCII码&#52488;&#46377;,进入帖子内容后才显示韩语字符초딩
H.   可组成计算机各种语言或协议关键字的字符以及字符组合 例如/0, \0,<>,<html>,#等
1,   字符串结束符,例如\0等,
2,   自定义的一些数据结构结束符号,例如 /0,^,^!等,例如pb模块曾经以^!作为一个帖子的结束符,曾经出现bug为在帖子内荣中发了^!^这样的字符导致帖子数据混乱;
3,   Html语言定义的字符集,例如:<html>,&nbsp的输入可能导致页面显示异常。
4,   Php或者其他语言中的关键字,例如$_ 等。
5,   用户输入的数据如果存在被转义并继承到url中的可能的话,需要测试字符中包含url特定字符,例如=&?<script>等,特殊字符有:!##^&^*&^*&*^#*$&*~_&!~^*~@#&@^%#(~@)#&;Html代码有:nt face="宋体"></textarea><script>alert("heelo")</script><textarea>;特殊串有:co=ji&tpl=tb&u=http://www.baidu.com
6,   http协议和url转义相关字符,例如中包含url地址,或者%31这样的转义字符。
7,   属于一个完整的http连接地址,url有时会被前端程序处理为<a href="http:…>+http模式,导致长度翻倍。
I.   汉字和上述字符(标点、特殊字符、日文字符)连在一起得情况
♀小☆光♀这个id 曾经在passport里无法登陆,类似的还有12※22、柠檬ゾ果┾☆婷☆、☆梦♀贝儿☆、521SHE_帅、﹀ァ某の角度。(这里只能靠case积累和对编码处理方式的分析来发现bug)
J.   可组成文件后缀的字符
例如.jpg,.rar等字符输入,这种较少见,通常在涉及本地文件提交或处理时才用到。
K.   Mysql相关字符转义处理
1,   在可能会被提交给数据库处理的数据中,输入/等mysql特定字符进行测试;
2,   编码或者转码后与/有关的字符;例如经典的错误DB query问题。当用户在tag域输入字符ó' 等一些字符时,会出现组装SQL语句时错误。这类字符的特点是: 一个大于ascii128编码的字符加上一个',在GBK编码过程中会被解析成为\汉',然后造成SQL语句的错误。
L.   其他特例
此类case不具有共性,需要和rd沟通后进行专门测试,例如汉字字符串签名问题等。
M.   最后,需要考虑字符长度、字符提交方式等问题,这部分与编码无关。
passport曾经有个bug,验证码输入框要求输入4位数字,但是当用户输入了4位汉字会core。在考虑长度时,要注意“字符串长度”和“用户输入字符个数”的区别。
附录——几个有意思的case
1,UTF8&GBK
在处理UTF8-->GBK的转换中会遇到一个问题,就是某些GBK字符会与UTF-8中2个字节编码的字符110xxxxx 10yyyyyy产生交集,从而导致这些编码被当成是UTF-8编码处理,进行了转码,从而出现乱码。
下面列出了GBK编码和UTF-8编码有交集的情况,其中第二列(如0xc080)表示编码,第一个汉字是这个编码被当成GBK理解时对应的汉字,[]中是编码被当成UTF-8理解时对应的字符。对应的结果为failed的行,表示被理解成UTF-8编码,转成GBK的时候,没有对应GBK编码的情况。参考附件《GBK编码和UTF-8编码的交集.doc》。
2, 无所不在的 \ 和 /
其一,\ 是SQL语句中的特殊字符,很多和数据库交互的模块都可能处理这个字符不当而出现SQL语句被截断的问题。最简单的就是用户在输入框里填写\后然后程序插入数据库时就会把\前后截断。但是\ 和 /在程序处理过程中还会不断衍生出来,这就麻烦了。例如Passport产品的detail.php程序在向数据库插入用户名时,曾经有过这样的case
A.   深爱谋女孓   %C9%EE%B0%AE%C4%B1%C5%AE%E6%DE 
B.   深愛謀女孓   %C9%EE%90%DB%D6%5C%C5%AE%E6%DE
B用户名本来应该按照策略处理为简体变为A用户然后插入数据库,结果由于%5C(\符号的编码)的存在,程序自己做了截断处理。这样的汉字还有 贼,转繁体后为 賊(%D9%5C)。因此当用户名中的gbk编码有%5C,也就是\符号的编码就会发生一些意向不到的问题。
其二,变形金刚 ó'(若打印版看不到这个字符请看wiki)。当用户输入字符ó' 等一些字符时,会出现组装SQL语句时错误。这类字符的特点是: 一个大于ascii128编码的字符加上一个',在GBK编码过程中会被解析成为\汉',然后造成SQL语句的错误。这类问题并非特殊字符问题,是SQL语句和字符组合在一起出问题。SQL语句会对\这个字符做特殊处理,而编码时为了避免\的截断已经做了处理,但是没有预料到这部分GBK编码后会产生一个新的\字符,导致出错。
其三,由于\ 和 /为url专有字符,因此相关问题几乎会成为UI和模板的bug导火索。例如url中如果包含"/"的转义"%3F",如果处理不当的话就会出现//的url,从而这个从apahce就会跳到错误页面,可参见"post.baidu.com/%2F"。
其四,\ 和 /还是正则表达式的关键字,反在模板,UI上的输入框处用到正则表达式的话,需要非常小心处理 \ 和 / 以及各种转码衍生出来的\ 和 /。
3,mysql转码——问题、新问题、新新问题
在mysql语句的构成中可以使用prestatement的方式进行语句的构建,但是通过sql语句的拼装方式也是不错的选择和被迫的选择(预先不知道sql语句的格式和字段)。不过这两者不存在显著的速度差别,sql语句的拼装相比prestatement来说速度降低不超过10%。 自己拼装sql语句在很多情况下容易出现问题,一些网站出现sql注入攻击也是这个问题导致的。
问题大致是这样的,将用户输入的字符串信息直接放入sql语句中,就会存在sql的解析错误和sql的注入。 例如,判断用户是否存在的sql语句为:select count() from username='$用户名'。用户输入: =' OR 1=1; select hex(a) where 'a'='a, 被翻译为:select count() from username='=' OR 1=1; select hex(a) where 'a'='a'。这时系统可能会认为用户存在。
问题大致是这样被解决的:mysql提供一个库函数mysql_real_escape来进行转码,这个转码的工作原理是将mysql使用的关键字进行转义,例如:' 会被转义成为 \' 。转义的方式主要使用\来进行。
新问题的产生:由于汉字字符编码的问题存在,转义过程中依然会出现错误。passport统计的结果是这种随机概率出现为万分之一。 例如用户输入ó' 。前面的字符为ASCII码的243,可以用小键盘敲入。此时,经过mysql的转码,被转移成为ó\', 而汉字编码会将ó\形成一个汉字,例如:橇',这时就会出现mysql错误的问题。
新问题的解决办法和新新问题:为了避免这种情况,我们将GBK编码修改为UTF-8编码后进行转义,然后再修改为GBK编码,修改后问题得到改善。但是新新问题接着出现,passport统计的结果是这种随机概率出现为百万分之一。 在处理blob信息时,会出现 随机串' 的情况,经过转码后,该信息被转化为 随机串\' 。在UTF-8对随机串编码后可能会多出一个\, 此时的串会变成 新随机串\\',此时就会多出一个'来,mysql语句拼装出现错误。
最后解决办法:mysql_real_escape本身没有任何问题,但是配合各种多字节
码,就会出现问题。为此,我们使用新的办法加以解决。利用mysql的hex函数和unhex函数。 hex函数和unhex函数分别实现串到16进制编码串转化和反转的功能。unhex函数很少有人使用,但是利用这个函数,可以解决转码问题。 首先,我们需要将出问题的字段(例如blob字段)的value进行一个hex处理,将blob信息转化为16进制编码串。然后将dst中的串进行unhex封装,unhex('%s')作为新的value。这样就不会出现转码上的问题了,而代价是两倍的转码临时空间(可以进一步考虑jl_str_tohex的原地转码)和额外的计算,不过节省了mysql转码的调用和设置字符集的开销(设置字符集需要和mysql交互)。具体的函数和最终的sql语句见wiki原文。
还会有新问题吗?现在还说不准,偶们正在继续挖掘呢 :)
4,隐形字符€ 
以前发现一个bug。是gbk转换到unicode的bug,在ui里可能的函数名是gbk2unicode、rputs2unicode或者其他什么名字里面有一句判断,(__u_char)(*s) > 127 如果只输入€字符则会在后面s += 2;越过\0这个结束标志。(__u_char)(€)的值是128,如用到就会出错。代码详见wiki。
这个字符处理不当带来的问题就是,如果€自己存在,则成为隐形字符(例如PS,IMAGE等产品),如果关键字为汉字中间夹杂€字符时,搜索结果为去掉€字符和最后一个汉字的结果。例如曾经在mp3中搜索哪吒€闹海,搜索框中显示:“哪吒€?> <input type=submit value=百度一下>……”并丢失“百度一下”的按钮。如果再根据这个结果出广告的话,那就更诡异了。
5,网页跳转二次转码bug
曾经有个bug,从百科,知道注册passport用户时,当用户输入个人信息包括co=ji&tpl=tb&u=http://www.baidu.com这样字符,或者<script>alert("heelo")</script>这样的字符串时,都不能正常处理,导致页面混乱。主要原因是ui在他页面跳转时对于用户已经输入的信息是转码后保存在页面里的,再进行二次转码时发生异常。当时导致异常的case包括
特殊字符:!##^&^*&^*&*^#*$&*~_&!~^*~@#&@^%#(~@)#&
Html代码:nt face="宋体"></textarea><script>alert("heelo")</script><textarea>
特殊串:co=ji&tpl=tb&u=http://www.baidu.com
6,href——长度翻倍的url超链接
以前贴吧发现一个问题,很有意思。现象是帖子内容浏览页出现超大页面,超过UI和apache的页面buffer大小(500k),导致页面build出错。正常情况下,帖子的最大帖子长度为5K,每页最多显示50个帖子,这样页面也就是250K左右,绝对不会超过500K的。但是线上情况是,用户发了一页内容基本全是链接的帖子。对于链接,例如[url]http://post.baidu.com/f?kz=73086208[/url],Html语言中会在其前面加上<a href="[url]http://post.baidu.com/f?kz=73086208[/url]" 。这样,链接内容相当于被写了两遍,加上页面中一些其他的内容,使得页面大小超过500k。这样的情况是我们在测试设计的时候没有考虑到的。现在我们对这个问题的解决方式是增大页面buffer的大小到700K。
其实,即使buffer开到这么大,在一些特殊情况下仍然会有问题。例如,现在我们对于html语言中的特殊字符,例如 “<”在页面展示的时候是强制转成“&lt”,这样,一个字符变成了3个字符,如果用户发一页全是 “<”的帖子时,buffer还是会不够。好在不是所有人都这样发贴的,因此对于这样的“极品”用户,我们目前的策略是忽略 :-)
395°/3910 人阅读/4 条评论 发表评论

小窝  2011-02-26


付民  2011-02-28

分享了,哈哈。。。


杨一  2011-03-02


张华  2014-03-25


登录 后发表评论