gpt4 book ai didi

c++ - "printf("%s 行的内存漏洞应该是 %s", argv[1]);"被描述为堆栈溢出?

转载 作者:IT老高 更新时间:2023-10-28 22:21:22 26 4
gpt4 key购买 nike

今天,我从 Elance.com 参加了一个简短的“C++ 技能测试”。一个问题如下:

What is the security vulnerability of the following line of code:

printf("%s", argv[1]);

Option 1: Format String

Option 2: Stack Overflow <-- This was marked by Elance as the correct answer



在看到问题的最初几秒钟后,用户被提供 10 秒钟来回答这个问题(或自动使问题失败)。 (还有另外两个明显不相关的答案没有被 Elance 标记为正确答案。)

我在找 缓冲区溢出 缓冲区溢出 作为一种选择。

我本能地不喜欢答案堆栈溢出,因为在我的 10 秒内,我在精神上使用了我认为是 standard definition of "Stack Overflow" 的东西。 :

In software, a stack overflow occurs when the stack pointer exceeds the stack bound. The call stack may consist of a limited amount of address space, often determined at the start of the program ...



根据“堆栈溢出”的这个定义, 在没有堆栈溢出的情况下,缓冲区溢出是完全可能的 ;仅当程序尝试 时才会发生堆栈溢出。在调用程序的总堆栈分配之外写入 (无论是由于缓冲区溢出,还是由于其他原因是合法的写入,例如为基于堆栈的变量分配内存过多次)。

我 10 秒的直觉告诉我,“缓冲区溢出”是对上面有问题的代码行的更准确描述 - 因为通常(根据我的经验)有足够的空字符( '\0' )通过 RAM 中的垃圾数据填充到在这种情况下,通常会避免实际的堆栈溢出,但实现中的缓冲区溢出似乎是合理的,甚至是可能的。 (但 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 并打算认真对待与组织一起进行有问题的测试。但是,对于本帖中讨论的问题,我不确定问题/答案是否有问题。

最佳答案

这里没有潜在的堆栈溢出。

标准保证argc是非负的,这意味着它可以是 0 .如 argc为正,argv[0]通过 argv[argc-1]是指向字符串的指针。

argc == 0 ,然后 argv[1]不仅仅是一个空指针——它根本不存在。在这种情况下,argv[1]尝试访问不存在的数组元素。 ( argv[1] 等效于 *(argv+1) ;允许添加指针,但取消引用具有未定义的行为。)请注意,在这种情况下,程序名称可以通过 argv[0] 访问。不可用。

argc==1 ,然后 argv[1] == NULL .正在评估 argv[1]是完全有效的,但它产生一个空指针。将空指针传递给 printf"%s"选项具有未定义的行为。我想您可以将其称为格式字符串问题,但真正的问题是在需要指向字符串的非空指针时使用空指针。

argc >= 2 ,然后 argv[1]保证指向一个字符串,printf("%s", argv[1])将简单地打印该字符串的字符,直到但不包括终止 '\0' (保证存在)。

在这种情况下仍然存在潜在的漏洞。报价N1570 7.21.6.1 第 15 段:

The number of characters that can be produced by any single conversion shall be at least 4095.



(N1570 是 C 标准的草案;C++ 指的是 C 标准的部分标准库。)

这意味着实现可能会限制 printf 产生的字符数。称呼。在实践中,可能没有理由强加一个固定的限制; printf可以简单地打印字符,一次一个,直到到达字符串的末尾。但原则上,如果 strlen(argv[1]) > 4095 ,如果当前的实现强加了这样的限制,那么行为可能是未定义的。

尽管如此,这并不是我所说的“堆栈溢出”——特别是因为 C++ 标准不使用“堆栈”这个词(除了对“堆栈展开”的几个简短引用)。

大多数这些问题可以通过首先检查来避免:
if (argc >= 2) {
printf("%s", argv[1]);
}

或者,如果您感到偏执:
if (argc >= 2 && argv[1] != NULL) {
printf("%s", argv[1]);
}

关于c++ - "printf("%s 行的内存漏洞应该是 %s", argv[1]);"被描述为堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24232937/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com