繁体   English   中英

如何使用 scanf 避免缓冲区溢出

[英]How to avoid buffer overflow using scanf

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

int main(int argc, char **argv) {
    char first_name[20];
    char last_name[20];
    int student_num;
    char debts[1];

    printf("Enter name:");
    scanf("%s", first_name);
    printf("Enter lastname:");
    scanf("%s", last_name);
    printf("Enter six bits length student ID:");
    scanf("%d", &student_num);
    printf("Do you have debts for university [Y/N]?");
    scanf("%s", debts);

    printf("\nYour name is %s %s.\n", first_name, last_name);
    printf("Your Student ID is %d.\n", student_num);
    printf("Debts: %s.\n", debts);
    return (EXIT_SUCCESS);
}

如何避免此代码中的缓冲区溢出? 我希望我的代码产生这样的输出:

Enter name:Enescekilokoneyasharrontannamyantoniaaquin
Enter lastname:Basenau
Enter six bits length student ID:456789
Do you have debts for university [Y/N]?YES

Your name is **Enescekilokoneyashar** (only 20 bits from name input) *Basenau*.
Your Student ID is **393299**.
Debts: **Y**.

Process returned -1073741819 (0xC0000005)   execution time : 36.336 s
Press any key to continue.

我曾尝试使用:

scanf("%19s", first_name);

但它不像我期望的那样工作。 我需要找到另一种方法来验证输入参数以防止缓冲区溢出攻击并将输入限制为缓冲区大小。

您可以保留scanf的使用,但您需要将其可以占用的大小限制为目标缓冲区的大小,例如:

scanf(" %19[^\n]", first_name); //last destination buffer element is for null byte

请注意,此说明符可以解析空格,因此您可以输入包含多个单词的输入。

但是,它会在stdin缓冲区中留下一个\\n字符,或者在输入较大字符串时未解析的剩余字符,因此每次要解析新输入时都需要清除它,您可以使一个方便的函数,您可以在需要这种清除时调用它,使其成为一种模式:

void clear_buffer(){
    int c;
    while ((c = getchar()) != '\n' && c != EOF){
        continue;
    }
}

您的char debts[1]缓冲区也有问题,它太小而无法存储字符串,它需要至少有 2 个字符才能存储空终止符:

char debts[2];

电话将是:

clear_buffer();
scanf(" %1[^\n]", debts);

最后你应该验证scanf的返回,例如,在scanf("%d", &student_num) ,如果你输入字母字符而不是数字,函数将无法解析并返回 0,您也可以使其最多解析6 位数字,类似于:

clear_buffer();
if(scanf("%6d", &student_num) == 0){ // %6d limit the input to 6 digits
    //handle error
}

现场演示

如果你是在Windows中可以使用的微软文档中描述scanf_s() 在这里 还给出了一个例子:

char s[10];
scanf_s("%9s", s, (unsigned)_countof(s));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM