Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不带#的C文件?_C - Fatal编程技术网

不带#的C文件?

不带#的C文件?,c,C,假设您给出一个C源文件,其中最多包含300行代码 还假设在实现多个函数时,文件中不包含字符“#”(也就是说,文件中没有#includestatements,也没有包含“#”的其他语句) 我的问题是,上面的是否保证文件不会执行任何I/O操作?它是否保证文件不会擦除硬盘上的内容,或者做其他可疑的事情 (我应该得到100-200个单独的C文件,这些文件(如上所述)不包括char#。我被要求编写一个简单的程序,该程序将以编程方式检查没有#的单个C源文件是否可能涉及I/O、访问网络等) 考虑到不允许使用带

假设您给出一个
C源文件
,其中最多包含300行代码

还假设在实现多个函数时,文件中不包含字符“#”(也就是说,文件中没有
#include
statements,也没有包含“#”的其他语句)

我的问题是,上面的是否保证文件不会执行任何I/O操作?它是否保证文件不会擦除硬盘上的内容,或者做其他可疑的事情

(我应该得到100-200个单独的
C
文件,这些文件(如上所述)不包括char
#
。我被要求编写一个简单的程序,该程序将以编程方式检查没有
#
的单个
C源文件是否可能涉及I/O、访问网络等)

考虑到不允许使用带有
#
的语句,那么在这样一个
C
文件中,编码人员可以包含哪些最糟糕的代码,从而可能损坏运行该文件的人的系统


知道任何检查都不会产生100%的准确率——但我至少有兴趣做一些基本检查,如果发现一些表达式/关键字,这些检查将发出危险信号。你知道要找什么吗?

不,这不能保证。您可以生成扩展所有包含和宏的代码,您可以将其生成一个巨大的文件,然后编译它。。。该文件不包含任何预处理器指令,尽管它可以执行C在系统上通常可以执行的任何操作。

如果原始编码器包含内联汇编,则他们可以执行他们喜欢的任何操作,而无需导入任何库。

只需复制和粘贴标准文件类型和函数的定义即可(例如文件、fopen()、fprintf()、flocse())以这种方式,不需要包含,当文件被编译并链接到适当的库时,它将能够执行I/O。

不一定。大多数编译器会为隐式声明生成警告,但仍会链接到函数中。您可以生成io执行函数的列表,并查看它们是否被调用,但这仍然不能阻止内联asm调用与io相关的系统调用


您可能应该在沙箱中以低优先级运行,并查看它们使用strace之类的工具进行的系统调用。

C允许使用指针进行不安全的操作。例如,在没有ASLR的系统上,获取指向任意库函数的指针是很简单的。它不是很健壮,因为任何内存访问冲突都会杀死您,但至少如果你知道目标系统,这是可能的


ASLR使它稍微困难一些,但我假设您可以只获取一个指向堆栈上当前位置的指针,然后向上爬行,直到到达属于线程入口点的堆栈。这肯定会有一些有趣的指针。

缺少预处理器指令并不能保证除缺少之外的任何东西预处理器指令的定义

您仍然可以为感兴趣的任何库函数手动添加数据类型和函数原型。如果您熟悉底层平台,您可以完全绕过标准库,直接进行系统调用

很久以前,我看到一段代码(可能是IOCCC代码),它使用一个无符号字符数组来存储原始操作码,然后使用类型punning将其作为一个函数处理,比如

unsigned char instr[] = {0x00, 0x12, 0x33, ...};

void (*foo)(void) = (void (*)(void)) instr;
foo();
请注意,这依赖于未定义的行为和大量不可移植的假设,我甚至不确定这种方法是否还能奏效。但如果真能奏效,那么通过简单的源代码扫描就很难发现这一点

编辑

我找到了我一直在想的代码——这是1984年的一个条目。但它不像我描述的那样工作。嘿,我变老了,东西不再像以前那样粘在我的脑子里了

short main[] = {
277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
-113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#',
0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
'p', 072163, 'r', 29303, 29801, 'e'
};
以下是:

大奖: Sjoerd Mullender&Robbert van Renesse 毫无疑问,这个C程序是 和所有伟大的参赛作品一样,他们的成绩是令人满意的 为了防止洪水泛滥 类似的程序,我们要求程序是非机器特定的。 该计划被选为1987年t恤系列。 注意:如果您的机器不是Vax-11或pdp-11,则此程序将 无法正确执行。在以后的几年中,依赖于机器 不鼓励使用代码。 C启动例程(通过crt0.o)将控制权转移到一个位置 在本例中,main恰好位于数据区域中。 短裤的数组,通过使用 不同的数据类型恰好形成了一组有意义的PDP-11 和Vax指令。第一个字是PDP-11分支指令 分支到PDP代码的其余部分 调用将子例程的第一个字用作 要保存的寄存器掩码。因此在Vax上,第一个字可以是任何内容。 真正的Vax代码从第二个字开始。这个小程序 直接调用write()Unix系统调用以生成 屏幕上的信息。你能猜出打印的是什么吗?我们认识你 不能!:-) 版权所有(c)1984,兰登·柯特·诺尔。 版权所有。允许个人、教育或非营利用途 授予,前提是本版权和通知包含在其全部内容中 并且保持不变。所有其他用途必须事先获得书面许可 来自Landon Curt Noll和Larry Bassel。 再说一次,我不知道这个技巧是否适用于任何现代桌面操作系统,但找到它会很有趣

#
不是唯一可以启动预处理器指令的令牌<代码>??=
int puts(const char *s); int main(void) { puts("hi"); return 0; }