为什么在允许某些 Unicode 字符的注释中执行 Java 代码?
技术问答
181 人阅读
|
0 人回复
|
2023-09-12
|
以下代码输出Hello World! (不是真的,试试)。
9 _" v% z+ o+ M# }9 p6 S, r: X& D9 ypublic static void main(String... args) / The comment below is not a typo. // \u000d System.out.println("Hello World!");}原因是 Java 编译器将 Unicode 字符解析\u000d为新行并转换为:
0 C Q' r! l: C |# G/ Y. z# Hpublic static void main(String... args) / The comment below is not a typo. // System.out.println("Hello World!");}因此,评论被执行。
% `& W/ V# I' L' q1 M, A; X既然这可以用来隐藏恶意代码或任何邪恶程序员可以想到的东西,为什么在评论中允许呢?7 G; J5 l- h1 z. l6 U
为什么 Java 规范允许这样做?
- P; O7 M# o8 v/ U& Q% {
5 A+ M: J2 V$ u. l9 E1 ]6 Q 解决方案: 3 ?( D/ c4 J3 _- L2 M$ A! h
Unicode 解码发生在任何其他单词翻译之前。这样做的主要好处是它使 ASCII 和其他任何代码来回变得微不足道。你甚至不需要弄清楚评论的开始和结束!3 t* D9 y- d; b4 U( L
如JLS 第 3.3 节允许任何基于 ASCII 工具处理源文件:
: p' p! G7 j, ?- R5 |[…] Java 编程语言指定了 Unicode 编写的程序转换为 ASCII 的标准方法将程序改为基于 的标准方法ASCII 工具处理形式。[…]! E& g/ g& }9 g1 B
这为平台 Java 平台的关键目标。
6 L h( d, s0 s* M* P任何 都可以写入文件中的任何位置Unicode 字符是用非拉丁语记录代码用非拉丁语记录代码时,在注释中尤为重要。以如此微妙的方式干扰语义的事实只是一个(不幸的)副作用。
' F; J0 T% X* Y) K这个主题有很多问题,Joshua Bloch 和 Neal Gafter 的Java Puzzlers包括以下变体:
( V2 k6 d/ w8 X5 b0 @这是合法的 Java 程序?如果是这样,它打印什么?
. {" f3 F( ?2 l( t( i- Jjava\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020\u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020\u0020\u0020\u0020\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\u0022\u002b\u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d
: v) |# X+ _; D6 L2 B1 `(这个程序原本是普通的Hello World”程序。)# D4 g, y% o$ |1 T1 C
他们指出了以下几点:9 |0 A8 D0 u/ W. L* v7 X
更严重的是,这个谜题加强了前三个教训:当您需要以任何其他方式插入您的程序时,Unicode 转义是必不可少的。避免在所有其他情况下使用它们。 |
|
|
|
|
|