让我们考虑以下计划:
#include <stdlib.h>
int main(int argc, char **argv){
int a,b;
if (argc != 3)
return -1;
a = atoi(argv[1]);
b = atoi(argv[2]);
a = b ? a/b : 0;
return a;
}
任务是通过在命令行中提供参数来使程序崩溃。
答案 0 :(得分:18)
将a
作为平台的INT_MIN
和b
作为-1。然后你会在任何两台补充机上出现溢出错误,虽然这不一定是崩溃。
答案 1 :(得分:5)
这个问题的答案是:这取决于。
您需要了解的一个重要信息是atoi
如何实施以及是否符合标准。该标准对实现细节的描述非常少,并且对输入输出行为更具体。让我们假设一分钟它确实符合标准,并专注于实施。
有几种方法可以有效使用,其中一种方法是递归的。让我们假设它被实现为头部递归算法,这会强制堆栈的堆积。然后我可以通过提供一个足够长的参数来使这个程序崩溃,它强制atoi
进行深度递归以进行堆栈溢出,从而使应用程序崩溃。
答案 2 :(得分:2)
你可以通过消除过程向后工作:
1)你能以零除以最终结果吗?不见得。如果b为0,则最后一个表达式为0,如果不为0,则不会得到除以零。
2)你能提供不正确数量的参数并在阵列访问时崩溃吗?不是因为早期的argc检查
3)如果你的参数没有翻译成数字,atoi 应该返回一个数值。我认为这是库规范的一部分,因此不适用于实现变化,但我可能是错的。
所以我不知道你会在这里崩溃。
我唯一喜欢这个问题的是零除部分 - 它检查你是否理解?:运算符,0表示错误。我不喜欢atoi部分而没有让您访问参考手册。我必须检查文档以确定。
下溢/溢出的可能性太棘手恕我直言。如果您正在为软件安全工程师进行面试,那就太棒了,但我不会要求入门级候选人,甚至只是标准的编程工作。如果你来自其他语言(例如Python),那就特别困难了。
更新:我在几个引用上进行了在线搜索,似乎atoi应该在输入错误时返回0。例如,来自MSDN:
每个函数都返回int值 通过解释输入产生的 字符作为数字。回报 atoi和_wtoi的值为0,如果是 输入无法转换为值 那种类型。
答案 3 :(得分:0)
我看到的唯一可能的弱点是atoi()。也许如果它传递了足够大的字符串,它会以某种方式在其内部行为异常。除此之外,除以0除以参数计数。我能想到的唯一另一件事就是通过垃圾邮件将垃圾邮件发送到参数中来溢出操作系统缓冲区。不太可能。
答案 4 :(得分:0)
我不知道大多数操作系统如何传递argv数据。它是在堆栈上分配的吗?它的长度本身有限吗?
你能传递一个非常长的命令行参数并创建堆栈溢出吗?