危险的encodeURIComponent

javascript中的 encodeURIComponent() 方法很常用,MDN里在描述这个方法的时候,有提到这个异常: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

在下面这个case中,node.js里被发现一个严重bug: http://cnodejs.org/topic/4fd6b7ba839e1e581407aac8
当时所有connect的app都紧急修复大伙们之前都没有意识到这个问题的存在,直到遇到这个可怕的0xDFFF,实在是隐蔽,汗!

stackoverflow上有人给出了一个详细的解答,大致翻译一下,大伙看看:

同样也是遇到这个问题,为了发现问题所在,@Brett Zamir 写了一个遍历方法,把ucs-2的字符集扫描了一遍:

for (var regex = '/[', firstI = null, lastI = null, i = 0; i <= 65535; i++) {
    try {
        encodeURIComponent(String.fromCharCode(i));
    }
    catch(e) {
        if (firstI !== null) {
            if (i === lastI + 1) {
                lastI++;
            }
            else if (firstI === lastI) {
                regex += '\\u' + firstI.toString(16);
                firstI = lastI = i;
            }
            else {
                regex += '\\u' + firstI.toString(16) + '-' + '\\u' + lastI.toString(16);
                firstI = lastI = i;
            }
        }
        else {
            firstI = i;
            lastI = i;
        }
    }
}

if (firstI === lastI) {
    regex += '\\u' + firstI.toString(16);
}
else {
    regex += '\\u' + firstI.toString(16) + '-' + '\\u' + lastI.toString(16);
}
regex += ']/';
alert(regex);  // /[\ud800-\udfff]/

很快结果就出来了,\ud800-\udfff 这段的字符是有问题的,再写个脚本验证一下:

for (var i = 0; i <= 65535 && (i <0xD800 || i >0xDFFF ) ; i++) {
    try {
        encodeURIComponent(String.fromCharCode(i));
    }
    catch(e) {
        alert(e); // Doesn't alert
    }
}
alert('ok!');

上面的输出符合MSDN上说的:这些字符除了surrogates,即便是“non-characters”也都是合法的unicode序列。

surrogates就是上面扫描出来的危险字符集空间段,分为高位段,低位段

有了这个范围,你可以直接过滤掉这些危险字符,但是当这组字符成对出现的时候(高低位段的字符搭配),它们作为unicode扩展集字符又是合法的(utf-16)

alert(encodeURIComponent('\uD800\uDC00')); // ok
alert(encodeURIComponent('\uD800')); // not ok
alert(encodeURIComponent('\uDC00')); // not ok either

所以如果你只是想屏蔽这个段的字符

urlPart = urlPart.replace(/[\ud800-\udfff]/g, '');

如果你想屏蔽非法的字符,但是保留高低位合法组合的字符(utf-16字符,很少用到),可以这么搞:

function stripUnmatchedSurrogates (str) {
    return str.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])/g, '').split('').reverse().join('').replace(/[\uDC00-\uDFFF](?![\uD800-\uDBFF])/g, '').split('').reverse().join('');
}

var urlPart = '\uD801 \uD801\uDC00 \uDC01'
alert(stripUnmatchedSurrogates(urlPart)); // Leaves one valid sequence (representing a single

如果js native处理了这个问题,就可以免了这个猥琐的修补,多好啊,哼!

====== 翻译完毕 ====

补充:

上诉的高低位端,实际上是 UCS-2中的保留字段。 unicode字符集分为很多端,看这里 http://baike.baidu.com/view/40801.htm

D800-DBFF:High-half zone of UTF-16  utf-16 高位
DC00-DFFF:Low-half zone of UTF-16  utf-16 低位

utf-16的参考资料:http://zh.wikipedia.org/wiki/UTF-16, 其中描述到:

Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。

所以这个问题就清晰明了

补充: 感谢 @猎隼 的补充
decodeURIComponent()确实也是危险的存在, js的encodeURIComponent, decodeURIComponent 处理的都是utf-8编码的字符集。decodeURIComponent 一旦传入gbk的encode字符串,异常就会抛出,没有try catch就会搞死node进程。

参考:
http://stackoverflow.com/questions/16868415/encodeuricomponent-throws-an-exception

时间: 2024-09-20 00:46:21

危险的encodeURIComponent的相关文章

CCAI 2017 | 病人是否有生命危险?机器学习来告诉你——专访南加州大学终身教授刘燕

从早前的语音识别到后来围棋中的人机大战,人工智能技术早已不是"天边的云彩",遥不可及,而是更多的落地于生活,解决很多具体的问题.机器学习作为实现人工智能的方法,使用机器学习训练的模型广泛应用于复杂系统的预测问题,股市的涨跌,是否会发生自然灾害等这些通常凭借"经验"判断的问题统统可以使用机器学习来达到更加准确的预测.而这一切,都绕不开对于数据的分析研究. CCAI大会前夕,CSDN专访了南加州大学计算机系终身教授.机器学习中心主任刘燕,她的主要研究项目是时间序列和时空

SQL密码管理的六个危险判断

当管理SQL Server内在的帐户和密码时,我们很容易认为这一切都相当的安全.但实际上并非如此.在这里,我们列出了一些对于SQL Server密码来说非常危险的判断. 当管理SQL Server内在的帐户和密码时,我们很容易认为这一切都相当的安全.毕竟,你的SQL Server系统被保护在防火墙里,而且还有Windows身份验证的保护,所有用户都需要密码才能进入.这听起来非常的安全,特别是当你认为所有人都这么做的时候.可实际上,它并不像我们想象得那么安全. 在这里,我们列出了一些对于SQL S

CMS程序中的危险文件

对于别人的程序,在使用前最好先好好读一下程序的说明,毕竟程序是别人写的,写个说明当然是向使用者交待一些相关信息,另外,如果懂点程序,最好改一下比如说后台呀,数据库调用文件呀之类的,当然,如果你有能力发现漏洞,你就为官方补上这些漏洞呀         随着互联网的兴起,越来越多的人想拥有自己的网站,可是许多人都不太懂做网站或者是没时间做,所以借用别人的源码便成了一种流行的方式.正因为如此,才造就了如此不平静的网络世界,因为程序漏洞无处不在. 许多朋友谈起论坛就首先想到的是动网,因为它确实是国内最优

url传递中文字符,特殊危险字符的解决方案(仅供参考)urldecode、base64

web开发的过程中,当我们需要在url中传递中文字符或是其它的html等特殊字符时,似乎总会碰到各种各样的小问题,因为不同的浏览器对他们的编码又不一样.对于中文,一般的做法是: 把这些文本字符串传给url之前,先进行urlencode($text)一下. 但是对于一些很"危险"的字符,比如说html字符,甚至是SQL注入相关的字符,如果很明显的传给系统,出于安全考虑,系统一般都会把它们过滤掉的. 那么,如果我们需要保留这些危险字符,不被过滤,该这么办呢? 我想到的办法是先给它们 bas

MSSQL SERVER2000 安全配置 删除所有危险的扩展

MSSQL SERVER2000 安全配置,将有安全问题的SQL过程删除.比较全面.一切为了安全! 删除了调用shell,注册表,COM组件的破坏权限 MSSQL SERVER2000 安全配置 将有安全问题的SQL过程删除.比较全面.一切为了安全! 删除了调用shell,注册表,COM组件的破坏权限 MS SQL SERVER2000 使用系统帐户登陆查询分析器 运行以下脚本: use master exec sp_dropextendedproc 'xp_cmdshell' exec sp_

encodeURIComponent 方法

encode   将文本字符串编码为一个统一资源标识符 (URI) 的一个有效组件. encodeURIComponent(encodedURIString) 必选的 encodedURIString 参数代表一个已编码的 URI 组件. 说明 encodeURIComponent 方法返回一个已编码的 URI.如果您将编码结果传递给 decodeURIComponent,那么将返回初始的字符串.因为 encodeURIComponent 方法对所有的字符编码,请注意,如果该字符串代表一个路径,

不可大意!小心三类危险的TXT文件

什么,TXT文件也有危险?是的!TXT文件不仅有危险,而且可以是非常的危险!不过,严格说来,应该给这个所谓的"TXT"文件加个引号,因为它们是看起来是TXT文件,实则是隐藏了其真实扩展名的其它文件,但在普通人看来它们的确是"TXT"文件!下面就让我们一起来了解一下这些危险的"TXT"文件. 一. 隐藏HTML扩展名的TXT文件 假如您收到的邮件附件中有一个看起来是这样的文件:QQ靓号放送.txt,您是不是认为它肯定是纯文本文件?我要告诉您,不一定

escape,encodeURI,encodeURIComponent函数比较

比较|函数|escape|encodeuri|encodeuricomponent js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent 1.  传递参数时需要使用encodeURIComponent,这样组合的url才不会被#等特殊字符截断.                            例如:<script language="java

危险病毒卤猪活动频繁 Linux等系统不受影响

上海计算机病毒防范服务中心日前发出预警:近期一种通过U盘.移动硬盘等移动存储设备传播的危险病毒"卤猪"(Win32.iuhzu.a)活动频繁,用户在使用移动存储设备过程中一旦感染该病毒,可能导致系统运行异常甚至崩溃等严重后果. 据介绍,该病毒主要攻击Windows 2000,Windows XP,Windows Server 2003等微软操作系统, Macintosh,Unix,Linux等系统不受影响. 来自上海市信息化服务热线等反病毒机构的专家介绍,"卤猪"病