【问题标题】:Fixing code to mitigate against buffer overflows and invalid inputs修复代码以减轻缓冲区溢出和无效输入
【发布时间】:2019-12-11 18:27:42
【问题描述】:

如何使以下代码对缓冲区溢出和无效输入具有鲁棒性? 能否请您编辑我应该更改哪些部分!

#include <stdio.h>
#include <string.h>
void password();
int main()
{
password();
return 0;
}
void password()
{
int number;
printf("PLEASE ENTER YOUR PASSWORD \n");
while (1){
if((scanf("%d",&number)) != 1)
{
 printf("wrong input\n");
}
else {
 if (number==999)
 printf("\n----PASSWORD IS CORRECT-----\n\n");
 break;
 }
 else
 printf("\n Please enter a valid password (integer)\n");
 }
 }
}

【问题讨论】:

  • 欢迎来到 Stack Overflow!请edit your question 包括确切您的问题是什么。只是快速查看您的代码,似乎您在if (number==999) 之后缺少一个左括号。但我不知道这是否能解决您的问题除非您解释一下。请附上您的具体错误消息或不正确的行为,以及您为尝试自己修复它所做的工作。
  • @Das_Geek 在不对称{} 存在的情况下修复缩进(尽管通常是一项崇高的努力)是有风险的。
  • @Yunnosch 同意。虽然在这种情况下我相信我是正确的,否则第二个else 无处可去。
  • Dexter11 请提供您的代码的minimal reproducible example。这至少需要修复 {} 的可疑结构。
  • @Das_Geek 我也这么认为。但是您应用的缩进(尽管令人信服)实际上意味着插入 { 并且(仅在我看来)边界代码更改。请注意,我没有拒绝您的编辑,但也不会接受。也许其他人喜欢它,这对我来说很好。但理想情况下,Dexter 会自行修复代码。如果没有,那么在这个问题上花更多的时间是没有意义的。

标签: c


【解决方案1】:

对于您的代码,您将整数值解析为整数变量。因此,您的代码不包含缓冲区溢出漏洞。

对于格式化,您的代码可以忽略数字值之前的输入(例如 alpha),但它无法检查可解析整数值之后是否有无效输入。因此,999abc 的字符串将适用于您的原始代码。

为了防止这种情况,我让 scanf() 在整数值之后解析 1 个附加字符。该字符可以是任何字符,而不是行尾字符。如果 scanf() 可以读取该字符,则表示输入无效。无效输入的一些示例包括“999”、“999abc”和“999-assdf”。

因此,如果无效字符在整数值之前或只有无效输入,则 scanf() 返回值为 0,如果无效字符在整数值之后,则返回 2,如果它只是您打算读取的整数,则返回 1 .因此,对于有效整数值的成功解析情况,scanf() 返回值应该仅为 1。

因为当它失败时,必须刷新标准输入。因此,我用 getchar() 刷新标准输入。否则,那些无法解析的字符将被下一个 scanf() 读取。

更新:我只记得您也可以在没有数组的情况下读取该字符。因此,我更新了答案代码。此外,scanf() 有时可能成为漏洞的最明显的麻烦是在解析数字时,scanf() 不检查溢出并且没有办法修复它。除非您将 int32 的位数解析数量限制为 9 位。虽然 int32 有 10 位数字,但它可能会溢出多次,只有 9999999999。所以使用下面的示例代码,给出这个数字 2014339662823,它会将您的密码作为 999 传递。

有几种方法可以解决溢出问题,其中之一是将数字解析为更高的数据类型。例如,如果您需要 32 位的 int 值。将其解析为 int64。然后检查结果。但是,如果您想将数字解析为最高数据类型会发生什么。如果有的话,int128。那么唯一的方法就是将输入解析为字符串,然后自己检查并解析输入为int类型。

#include <stdio.h>
#include <string.h>
void password();
int main(){
  password();
  return 0;
} 

void password(){
  int number, c;
  char voidChar;
  printf("PLEASE ENTER YOUR PASSWORD \n"); 

  while (1){
    if((scanf("%d%[^\n]c",&number, &voidChar)) != 1){
      printf("Wrong input(Integer Only):\n");
      while((c = getchar()) != EOF && c != '\n');
      continue;
    } else {
      if (number==999){
        printf("\n----PASSWORD IS CORRECT-----\n\n");
        break;
      }
      printf("\n Please enter a valid password\n");
    } 

  }
}

因为你不知道什么是缓冲区溢出。下面的这段代码是为了演示一个缓冲区溢出的简单示例。运行下面的代码,输入“abcdefghijklmnopqrstuvwxyz012456Hello_World”,不带引号。运行之后,您仍然可以释放为“用户”变量分配的内存。但是,您将无法释放为“thisWillChange”变量分配的内存。在 scanf() 写入超出 malloc 为“用户”变量保留的内存边界后,其内存块已损坏。

#include <stdio.h>
#include <stdlib.h>

int main(void) {           
  char * user = (char * ) malloc(10);
  char * thisWillChange = (char *) malloc(10);

  puts("Please enter your password");
  scanf("%s", user);

  puts(thisWillChange);

  // abcdefghijklmnopqrstuvwxyz012456Hello_World
  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-11
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 1970-01-01
    相关资源
    最近更新 更多