为什么在允许某些 Unicode 字符的注释中执行 Java 代码?
技术问答
212 人阅读
|
0 人回复
|
2023-09-12
|
以下代码输出Hello World! (不是真的,试试)。
! L+ W, j9 m9 G3 lpublic static void main(String... args) / The comment below is not a typo. // \u000d System.out.println("Hello World!");}原因是 Java 编译器将 Unicode 字符解析\u000d为新行并转换为:
0 ` N4 L* R7 ]$ {public static void main(String... args) / The comment below is not a typo. // System.out.println("Hello World!");}因此,评论被执行。
( c' U& V. k4 y% u+ h& f既然这可以用来隐藏恶意代码或任何邪恶程序员可以想到的东西,为什么在评论中允许呢?
# ?! L7 m: M$ w& L( R为什么 Java 规范允许这样做?
( g/ g2 G& Z# l4 A% D 4 w5 r3 {. m: `; z$ _
解决方案:
: S% Y" f; `( V9 X Unicode 解码发生在任何其他单词翻译之前。这样做的主要好处是它使 ASCII 和其他任何代码来回变得微不足道。你甚至不需要弄清楚评论的开始和结束!$ S" m( ?" V' c$ ?" V0 g
如JLS 第 3.3 节允许任何基于 ASCII 工具处理源文件:
/ I! [7 j8 ?0 M- g" F. j% v[…] Java 编程语言指定了 Unicode 编写的程序转换为 ASCII 的标准方法将程序改为基于 的标准方法ASCII 工具处理形式。[…]
6 }9 h9 P: h- E8 n; n: V$ A3 o9 b这为平台 Java 平台的关键目标。
, p* j" Q; ^) _+ b任何 都可以写入文件中的任何位置Unicode 字符是用非拉丁语记录代码用非拉丁语记录代码时,在注释中尤为重要。以如此微妙的方式干扰语义的事实只是一个(不幸的)副作用。
/ {$ g8 M# G8 X" | l" k" _这个主题有很多问题,Joshua Bloch 和 Neal Gafter 的Java Puzzlers包括以下变体:
" d" t; ^3 d% ^* q这是合法的 Java 程序?如果是这样,它打印什么?7 r8 D% v- T1 q; t9 N
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
% Y! [. @; b: s& E(这个程序原本是普通的Hello World”程序。)
( ]# _. b6 A9 e# y2 |4 H2 L他们指出了以下几点:
. |+ Q) J# v+ z9 x; }* p8 d更严重的是,这个谜题加强了前三个教训:当您需要以任何其他方式插入您的程序时,Unicode 转义是必不可少的。避免在所有其他情况下使用它们。 |
|
|
|
|
|