为什么在允许某些 Unicode 字符的注释中执行 Java 代码?
技术问答
237 人阅读
|
0 人回复
|
2023-09-12
|
以下代码输出Hello World! (不是真的,试试)。
: J$ Q$ c( }( F, s. n, bpublic static void main(String... args) / The comment below is not a typo. // \u000d System.out.println("Hello World!");}原因是 Java 编译器将 Unicode 字符解析\u000d为新行并转换为:
" _) s; f$ f* Q% k* cpublic static void main(String... args) / The comment below is not a typo. // System.out.println("Hello World!");}因此,评论被执行。
* S7 V7 m% M2 {: x. s既然这可以用来隐藏恶意代码或任何邪恶程序员可以想到的东西,为什么在评论中允许呢?2 B# u" d/ r5 E& z5 I% s
为什么 Java 规范允许这样做?* }* a. h v7 y1 k; E# ?
; k" G1 {- u$ k: p
解决方案:
, u1 N' r8 L$ e2 [/ c( y" t3 k4 {% G! L, _ Unicode 解码发生在任何其他单词翻译之前。这样做的主要好处是它使 ASCII 和其他任何代码来回变得微不足道。你甚至不需要弄清楚评论的开始和结束!* i' @" ?2 C; ]2 n0 O% P V* u
如JLS 第 3.3 节允许任何基于 ASCII 工具处理源文件:- e. {# k; M4 P% K6 ^/ j% P
[…] Java 编程语言指定了 Unicode 编写的程序转换为 ASCII 的标准方法将程序改为基于 的标准方法ASCII 工具处理形式。[…]- D, s! T! {7 q% ^( I" x+ b3 n
这为平台 Java 平台的关键目标。
" I) S$ p, s6 D# P- Y任何 都可以写入文件中的任何位置Unicode 字符是用非拉丁语记录代码用非拉丁语记录代码时,在注释中尤为重要。以如此微妙的方式干扰语义的事实只是一个(不幸的)副作用。
# h+ _5 L. j3 {' q( {这个主题有很多问题,Joshua Bloch 和 Neal Gafter 的Java Puzzlers包括以下变体:
3 S2 f6 t8 |( I2 B5 b这是合法的 Java 程序?如果是这样,它打印什么?/ X% I2 G! _" y, K
java\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
B4 i- o1 g& `(这个程序原本是普通的Hello World”程序。)! l( u! o; d. j$ z
他们指出了以下几点:; c! H3 w+ D6 k( a; |7 g
更严重的是,这个谜题加强了前三个教训:当您需要以任何其他方式插入您的程序时,Unicode 转义是必不可少的。避免在所有其他情况下使用它们。 |
|
|
|
|
|