【问题标题】:String with buffer overflow缓冲区溢出的字符串
【发布时间】:2022-11-30 03:25:40
【问题描述】:

我正在尝试创建一个读取一些字符串的程序,但是当我测试一个很长的字符串时,会发生溢出,并且我已经看到的所有解决方案都不起作用。下面的代码是:

#include <stdio.h>

int main()
{
    char nome[201] = {0};
    char cpf[15] = {0};
    char senha[101] = {0};
    scanf("%200s", nome);
    scanf("%14s", cpf);
    scanf("%100s", senha);
    printf("nome: %s\n", nome);
    printf("cpf: %s\n", cpf);
    printf("senha: %s\n", senha);
    return 0;
}

此代码应该防止溢出,但以下字符串:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaassssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

我试图将字符串放入所有输入中,当涉及到第二个时,程序完成并且溢出内容转到第三个字符串。

【问题讨论】:

  • scanf("%200s", nome); 最多读取 200 个非空白字符,将其余字符留在 stdin 中以供下一个输入函数使用。代码正在按应有的方式运行。你的期望是错误的。如果你想消耗和抛出超过 200 个字符,你需要其他代码。
  • 爱德华多莫斯卡,缓冲防止溢出。 3“aaa ... sss”输入你想要什么输出?
  • 我想要的输出是字符串受限的变量,而不是跳过此输入的第三个变量。例如,在第二个变量中,我只需要此输入的前 14 个字符,最后一个输入也相同
  • 爱德华多·莫斯卡,好的。如果输入是"aaa bbb ccc\n" "ddd eee fff\n" "ggg hhh iii\n",你想要什么输出? (如果输入行包含空格?)
  • 输出需要相同,因为这些输出的长度都不大于分配给变量的内存。

标签: c


【解决方案1】:

您按顺序要求输入。第一个最大长度为 200 个字符,第二个为 14 个字符,第三个为 100 个字符。您输入的字符串为 160。

现在忽略第一个变量(因为没有溢出),C 从输入缓冲区中取出前 14 个字符并将它们放入第二个变量中。它以空终止符终止它。没有发生溢出。

现在我们需要获取第三个变量的数据。具体来说,我们需要获取接下来的 100 个字符,或者直到下一个空格的所有字符,以较短者为准。我们放了 160 个字符进入输入缓冲区(你的键盘粉碎)并取出 14。因此,输入缓冲区中仍有 144 个字符。不再需要交互式地等待输入; C取前100那些字符并将它们放入第三个变量中,以空终止符终止。现在我们所有的输入都已经完成,所以程序继续。

这里不存在缓冲区溢出漏洞。该程序定义明确,可以按照您的要求进行操作。您要求它从输入缓冲区中读取三次。您从未说过“来自三个不同的行”。如果你想做, 然后你需要自己处理定界符。在 C++ 中,有一个名为 std::getline 的函数可以为您完成此操作,但在 C 中,您需要自己手动读取(并丢弃)该行的其余部分。这样的东西就足够了。

scanf("%200s%*[^
]", nome);

* 表示新读取的值应该不是存储在任何地方,[^ ] 表示应该读取零个或多个非换行符,直到模式不再匹配(即直到下一个字符是换行符或我们到达文件末尾)

【讨论】:

  • scanf("%200s%*s", nome); 将在输入小于或等于 200 个非空白字符时产生问题,因为它需要第二个“单词”。
  • 为了丢弃该行的剩余部分,我推荐scanf( "%*[^ ]" );
  • @AndreasWenzel scanf( "%*[^ ]" ); 几乎丢弃了该行的其余部分。它不会丢弃行的' 'scanf( "%*[^ ]" ); scanf( "%*1[ ]" ); 确实如此。
猜你喜欢
  • 2013-10-22
  • 2021-12-10
  • 2014-11-07
  • 2013-04-12
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
相关资源
最近更新 更多