什么是以下代码行的安全漏洞: printf("%s", argv[1]);
选项1:格式化字符串
选项2:堆栈溢出 <-- 这被Elance标记为正确答案
用户有10秒钟时间回答这个问题,在最初几秒钟看到问题后(否则自动失败)。 (还有两个明显不相关的答案,未被Elance标记为正确答案。)
我在寻找缓冲区溢出或缓冲区溢出作为选项。
本能地,我不喜欢答案“堆栈溢出”,因为在我的10秒钟内,我精神上使用了我认为是堆栈溢出的标准定义:
在软件中,当堆栈指针超过堆栈边界时,就会发生堆栈溢出。调用堆栈可能由有限的地址空间组成,通常在程序开始时确定...根据“堆栈溢出”的定义,仅当程序尝试在调用程序的总堆栈分配范围之外进行写入(无论是由于缓冲区溢出还是其他合法的写入,例如为基于堆栈的变量分配内存过多)时,才完全可能发生缓冲区溢出而不发生堆栈溢出。
我的第一反应告诉我,“缓冲区溢出”是上述有问题的代码行的更准确描述,因为通常(根据我的经验),在RAM中的垃圾数据中有足够的空字符('\0')来避免实际的堆栈溢出,在这种情况下,实现中的缓冲区溢出似乎是合理的可能或甚至是可能性较大的。但是,printf在此处读取垃圾内容的可能性可能假定argc == 1,因此不存在用户提供的argv[1];如果argv[1]存在,则可以认为调用函数未插入NULL。在问题中没有说明是否存在argv[1]。
因为我想象中可能存在缓冲区溢出问题,即使没有堆栈溢出,我选择了“格式化字符串”,因为只需传递不同的格式化字符串,例如“%.8s”,就可以大部分避免该问题,因此它似乎是一个更通用的答案,因此更好。
我的答案被标记为错误。正确答案被标记为“堆栈溢出”。
我现在意识到,也许假设
argv[1]
存在,那么唯一可能的缓冲区溢出是堆栈溢出,在这种情况下,“堆栈溢出”实际上可能是正确的答案。然而,即使在这种情况下,称之为“堆栈溢出”是否不太奇怪?假设 argv[1]
存在,难道不是“缓冲区溢出”更好地描述了这个问题吗?如果 argv[1]
不存在,那么将问题称为“堆栈溢出”,而不是更准确的“缓冲区溢出”,是否基本上是不正确的?我想征求此网站专业人士的意见:用“堆栈溢出”来定义上述代码行的内存安全问题是否合适?或者,“缓冲区溢出”或“缓冲区越界”显然更好地描述了该问题?最后,在题目所提供的两个选项中,答案是否含糊不清,还是“堆栈溢出”(或“格式字符串”)显然更好的答案?
与Elance测试相关的旁注(与此发布的问题无关)
Elance的所有“C++技能测试”问题都与C++特定功能,如类、模板、STL中的任何内容或多态的任何方面无关。每个问题都是简单的C语言问题。
因为在Elance所谓的“C++技能测试”中有许多(至少3个)其他问题是毫无疑问错误的(例如这个问题:给定sizeof(int)==sizeof(int*)
和sizeof(int)==4
,那么在代码int *a, *b; a=b; b++; b-a;
中,b-a
是多少,正确答案列为4
,而实际上正确答案是1
),并且由于测试中没有C ++特定问题,我已经联系了Elance,并计划与该组织认真解决其有问题的测试。但是,对于本帖讨论的问题,我不确定问题/答案是否有问题。
argv[1]
可以是任何东西。可能没有参数传递给程序,在这种情况下,它指向 "空间中的某个地方"(或者可能是 NULL)。通常,打印一个未知字符数的字符串(基本上不带nul
结尾)应该不会导致堆栈溢出,因为用于打印的 "堆栈" 不是很多 - 我相信。只有参数(指向字符串的指针)被推送到堆栈上 - 不清楚这是否会导致堆栈溢出(除非你已经用完了堆栈并且到达此处 - 这将是压垮骆驼的最后一根稻草)。 - Floris