简体   繁体   中英

Buffer overflow in scanf()

I was looking online for solution for this problem with no result. I'm trying to do while loop to read only characters using scanf(). If user type more than 3 characters than it will display error.

However, my code works partially if I type 3 characters and press enter it works without executing loop this is what I want. If I type 4 characters and press enter also works it executes loop and says "too long" same for 5 char + enter also what I want.

However, if I type 7 characters and enter it executes loop and exits program right away. Any advice?

Ps. I apologize for any grammar error but English is my second language.

#include<stdio.h>
int main(){
char alo;
char alo1; 
char alo2; 
char alo3;

printf("enter 3 characters: ");
scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 

while(alo3!='\r' && alo3!='\n'){
    printf("too long \n");
    printf("enter ");       
    scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 
}   
return 0;
}

Using scanf() only

Using just scanf() to achieve this requires a certain amount of jiggery-pokery. It isn't the best way to code it, but…

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;

    printf("enter 3 characters: ");

    while (scanf(" %c %c %c%c", &alo0, &alo1, &alo2, &alo3) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;
        printf("too long\n");
        printf("enter 3 characters: ");
    }

    printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    return 0;
}

The while() condition uses scanf() to read four characters, skipping white space before the first three. Note that it is OK to put newlines in between characters; scanf() doesn't care. If you want line-based input, scanf() is simply the wrong tool for the job! However, assuming that 4 characters are read and the fourth is neither carriage return nor newline, then the code uses:

        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;

to read any characters up to, but not including, a newline. It doesn't mind if there are no such characters so scanf() returns 0. The code then prompts you to enter the correct data and goes around to the main scanf() . This skips the newline that was left behind and then looks for three characters again.

When the while loop exits, it could be because it got three characters and a newline, or because it got fewer characters and EOF, or because the clean-up scanf() detected EOF. The code doesn't attempt to distinguish between these (but it should) and simply prints out three values. Fixing that is not dreadfully hard; simply assign the return from each scanf() to a variable and then test that after the loop:

int rc;
while ((rc = scanf(…)) == 4 && …)
{
    …
    if ((rc = scanf(…)) == EOF) 
        break;
    …
}

if (rc == 4)
    printf(…);
else
    printf("Didn't get 3 characters as requested\n");

Using fgets() for line input

Personally, I think it is easier/better to use fgets() and sscanf() like this:

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;
    char buffer[4096];
    int rc = 0;

    printf("enter 3 characters: ");

    while (fgets(buffer, sizeof(buffer), stdin) != 0 &&
           (rc = sscanf(buffer, " %c %c %c%c", &alo0, &alo1, &alo2, &alo3)) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        printf("too long\n");
        printf("enter 3 characters: ");
        // In case you get 4 characters but the 4th was not a newline
        // and then you get EOF
        rc = 0;
    }

    if (rc == 4)
        printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    else
        printf("Didn't get 3 characters as requested\n");
    return 0;
}

This could report the string that was too long, or otherwise incorrect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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