Fixing code to mitigate against buffer overflows and invalid inputs

For your code, you are parsing an integer value to an integer variable. Thus, your code does not contain a buffer overflow vulnerability.

For formatting, your code can disregard input such as alpha before number values, but it can’t check whether if there are invalid inputs after the parse-able integer value. Thus, strings that are 999abc will work with your original code.

To prevent, that, I make scanf() parse 1 additional character after the integer value. That character could be anything, just not an end of line character. if scanf() could read that character, that means the input is invalid. Some examples of invalid inputs are “999 “, “999abc”, and “999-assdf”.

Thus, scanf() return value is 0 if invalid characters are preceding the integer value or when there are only invalid inputs, 2 if invalid characters are succeeding the integer value, 1 if it is only the integer that you intended to read. Thus, scanf() return value should only be 1 for a successful parse case of a valid integer value.

For when it fails, stdin has to be flushed. Thus, I flush stdin with getchar(). Otherwise, those unparsable characters will be read by the next scanf().

Updated: I just remembered that you could also read that character without an array. Thus, I updated the answer code. Also, the most noticeable nuisance of scanf() that can sometimes become a vulnerability is when parsing numbers, scanf() does not check for overflow and there is no way to fix that. Unless you limit the amount of digit parsing to 9 digits for int32. Although for int32 there are 10 digits, it can overflow multiple times with just 9999999999. So with the example code below, giving this number 2014339662823, it will pass your password as 999.

There are a few methods to beat that overflow nuisance and one of those is to parse a number into a higher data type. For example, if you need an int value of 32 bits. Parse it into an int64. Then check the result. But then what happens if you wanted to parse the number into the highest data type. Like if available, int128. Then the only way is to parse the input as a string and then check and parse the input to an int type by yourself.

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

  }
}

Since you don’t know what is a buffer overflow. This code below is to demonstrate a simple example of a buffer overflow. Run the code below and for input, put “abcdefghijklmnopqrstuvwxyz012456Hello_World” without quotes. After you run that, you will still be able to free the memory allocated for the “user” variable. However, you won’t be able to free the memory that was allocated for the “thisWillChange” variable. Its block of memory is corrupted after scanf() wrote beyond the bound of memory that was reserved by malloc for the “user” variable.

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

Leave a Comment