c - 修复代码以缓解缓冲区溢出和无效输入

标签 c

如何使以下代码能够抵御缓冲区溢出和无效输入? 您能编辑一下我应该更改哪些部分吗?

#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");
 }
 }
}

最佳答案

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

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

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

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

当失败时,必须刷新 stdin。因此,我用 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”(不带引号)。运行后,您仍然可以释放为“user”变量分配的内存。但是,您将无法释放为“thisWillChange”变量分配的内存。在 scanf() 写入超出 malloc 为“user”变量保留的内存范围后,其内存块被损坏。

#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;
}

关于c - 修复代码以缓解缓冲区溢出和无效输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59291939/

相关文章:

c - 在 C 循环中打印 char 的输入

c - 在C中如何防止UDP数据包被重复或丢弃?

c - 如何确定 gcc 默认将哪些命令行选项传递给 ld?

android - Android 7 中的 IPerf3 执行不起作用

c - 什么会导致 exec 失败?接下来发生什么?

c - 为什么许多窗口的窗口创建速度很慢?可以更快吗?

c - 使用 fread 更改结构值 C 时出现问题

c - 如何在C中将整数放入 vector 中?

c - 错误 : expected '=' , ',' , ';' , 'asm' 或 '__attribute__' 在 enableSSHSFTPKeyMode 之前

代码第一次编译时给出正确的数字,第二次给出随机数