clang 没有停留在 #include "/dev/whatever"

clang not stuck at #include "/dev/whatever"

我在做在线评委代码安全的项目。一个可能的漏洞是当有人上传一段这样的代码时:

#include "/dev/stdin"
#include "/proc/self/fd/0"
#include <stdio.h>
// Other legitimate code

我正在尝试重现它。当使用 gcc foo.c 编译它时,gcc 会卡住并从终端读取,直到 EOF (Ctrl-D),如预期的那样。当我clang foo.c,好吧,什么也没发生。 Clang 的行为就像这些行从未存在过一样。然后我尝试了这些代码:

#include "/dev/zero"
#include "/dev/random"
#include "/dev/ram"

仍然没有运气。为什么 Clang 忽略所有这些?我怎样才能让 Clang 被 #include-ing 卡住?

C 标准规定

A preprocessing directive of the form

# include <h-char-sequence> new-line

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence [...]. How the places are specified or the header identified is implementation-defined.

A preprocessing directive of the form

# include "q-char-sequence" new-line

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

# include <h-char-sequence> new-line

with the identical contained sequence (including > characters, if any) from the original directive.

(C2011 6.10.2/2-3;已强调)

特别是,绝对不需要 C 实现来将 header 具有绝对路径形式的名称 解释为 绝对路径。这样的 header 名称甚至不在符合标准的编译器必须为其提供唯一映射的名称中。

符合标准的 C 编译器必须记录所有 implementation-defined 行为。 GCC 确实提供了涵盖该领域的文档,但这些文档似乎并未明确说明绝对路径。然而,在我看来,GCC 只使用给定的路径似乎是合理的。 Clang 的行为显然不同,但它没有记录其 implementation-defined 行为(因此在这方面是 non-conforming)。它的输出可能会提供有关它正在做什么的线索。

更新:

Why does Clang ignore all these?

您可以检查其源代码以确定 Clang 正在做什么的细节,但只有 Clang 开发团队可以肯定地告诉您为什么 Clang 是以这种方式实现的。也许它的开发人员预料到您的 hosted-service 用例并有意强化 Clang 以抵抗您描述的那种攻击。

How can I make Clang stuck by #include-ing something?

您已经尝试过的方法似乎是最有可能的。如果它们不起作用,那么可能就没有办法以这种方式破坏 Clang。

创建一个 fifo,并 #include 它。 请注意,这似乎只是停止了 clang;它没有从中读取。 这可能只在 clang 团队看到这个之前有效....