我丢,谁在注释里给我下毒了???

5,250次阅读
2条评论

共计 1245 个字符,预计需要花费 4 分钟才能阅读完成。

丢!!!

突然发现公司项目里的代码注释被执行了!!!写了这么一行注释!!!

我丢,谁在注释里给我下毒了???

按常规思路,这行代码被注释了,控制台应该不会有执行结果,但是却出现了如下返回结果。

我丢,谁在注释里给我下毒了???

到这里,我们能大概猜测是 Unicode 解码发生在任何词汇解码之前。而 \u000d 是一个换行符,因此对注释进行了终止导致换行符后面的注释代码被执行了。

什么是 Unicode 逃逸?

我去 oracle 官网查看了一下 Java 语言规范(JLS 3)相关的解释,大意如下:Unicode 转义用于表示仅包含 ASCII 字符的 Unicode 符号。当您需要插入无法在源文件的字符集中表示的字符时,它将派上用场。JLS 3.3节的相关说明,Unicode 转义包含一个反斜杠字符(\),后跟一个或多个’u’字符和四个十六进制数字。

我丢,谁在注释里给我下毒了???

因此,例子中的 \u000d将被视为换行符。

下图为官方 JLS 文档。

我丢,谁在注释里给我下毒了???

这种机制的好处在于它可以在 ASCII 和任何其他编码之间来回切换,并且不需要你弄清楚注释的开始和结束位置!

分析求证

为了证实是不是我们分析的那样,我用了 Java 自带的工具 native2ascii 来将具有任何支持的字符编码的文件转换为具有 ASCII 或 Unicode 转义的文件。

我丢,谁在注释里给我下毒了???

执行如下命令便一目了然了。

我丢,谁在注释里给我下毒了???

我丢,谁在注释里给我下毒了???

我可以发现转换后的代码被换行了!

其实,我也可以通过查看 class 字节码来发现其中的端倪。

我丢,谁在注释里给我下毒了???

看来跟我们之前分析的一样。

结尾

这个骚操作也保证了 Java 核心思想 —— 平台一致性。

虽然这个方式处理机制看似优雅,但是,它却带来了副作用(干扰语义),尤其是在评论中,我们一定要注意!

好了,留个问题给各位,新建一个 Hi.java 文件,将下面的 Unicode 码拷贝到文件,看看执行结果会是什么?

\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0063\u006c\u0061\u0073\u0073\u0020\u0048\u0069\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0020\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0061\u0072\u0067\u0073\u0029\u007b\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020\u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d
mp_wx_9dc2a13583

共计21人点赞,其中1人来自小程序

正文完
 21
沛霖主页
版权声明:本站原创文章,由 沛霖主页 2023-04-24发表,共计1245字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(2条评论)
eveve 评论达人 LV.1
2023-05-05 17:21:17 回复

沛霖哥哥好厉害!!! :evil:

 Macintosh  Chrome  中国浙江省温州市移动