Dawn Capria
Dawn Capria

Reputation: 3

stack overflow runtime error c++

I am writing a program for class for a password validator. I need the password to be at least 6 characters, but I am also limiting it to a max of 10 (not required but wanted to).

The program works great and my other validations work until I try to add a password with more than 10 characters. I can go through and reenter a new password, and I get the message that it is now a valid password. But then I get a the following error:

Run-Time Check Failure #2 - Stack around the variable 'password' was corrupted.

I can get around the error if I set the width, but I know this isn't the correct way to handle it. Also I would think that by setting the width that the user would not be able to enter anything other than that size.

Here is my code:

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cctype>

using namespace std;

//Function prototypes
bool validatePassword(char *);                      //function to test pw requirements
bool validateUppercase(char *);                 //function to test for upper case value
bool validateLowercase(char *);                 //function to test for lowercase value
bool validateNumber(char *);                    //function to test for a number value
bool validateLength(char *);                    //function to test for password length

int main()
{
    //Variabes
    char password[11];                              //set the maximum number of char for password include the end     delimiter
    int size;                                       //size of the array

    //Prompt user to enter a password based on criteria

    cout << "Please enter a password that meets the following criteria: \n";
    cout << "1. A minimum of 6 characters up to a max of 10. \n";
    cout << "2. Contains atleast one uppercase and one lowercase character. \n";
    cout << "3. Contains atleast one number. \n\n";
    //cout << "****Please note if you have more the 10 characters \n";
    //cout << " the program will only accept the first 10***\n";
    cout << "\nPlease enter your password: ";
    cin >> password;
    //cin  >> setw(10) >> password;             //set this so I would not get a runtime error

    size = strlen(password);                        //determines the length of the password

    do
    {
        while (!validatePassword(password))     //if the functions returns a false value
        {
            cout << "\nYour password does not meet the requirements. ";
            cout << "\nEnter a new password: ";
            cin >> password;
            size = strlen(password);
        }
    } while (size > 10);

    if (validatePassword(password))
    {
        cout << "\nYour password " << password << " meets the requirements. \n";    //if the function returns a true value

    }

    system ("pause");

    return 0;

}

//This function calls the other validation functions 
bool validatePassword(char *pass)
{
int size = strlen(pass);
return (validateLength(pass) && validateUppercase(pass) &&         validateLowercase(pass) && validateNumber(pass) == true);
}

//This function validates the length of the password
bool validateLength (char *pass)
{
    int size = strlen(pass);
    if (size >= 6 && size < 10)
        return true;
    else
    {
        cout << "\n\nThe password you entered either contained to little or to many characters.";
        cout << "\nA minimum of 6 characters to a maximum of 10 is required.";
        return false;
    }
}

//This function checks to see if the password contains an uppercase char
bool validateUppercase(char *pass)
{
    int size = strlen(pass);
    for (int count = 0; count < size; count++)
    {
        if (isupper(pass[count]))
            return true;
    }

    cout << "\n\nThe password must contain at least one uppercase  character. ";
    return false;
}

 //This function checks to see if the password contains an lowercase char
 bool validateLowercase(char *pass) 
 {
    int size = strlen(pass);
    for (int count = 0; count < size; count++)
    {
        if (islower(pass[count]))
            return true;
    }

    cout << "\n\nThe password must contain at least one lowercase character. ";
    return false;
 }

//This function checks to see if the password contains an number char
bool validateNumber(char *pass)
{
    int size = strlen(pass);
    for (int count = 0; count < size; count++)
    {
        if (isdigit(pass[count]))
            return true;
    }

    cout << "\n\nThe password must contain at least one number. " ;
    return false;
 }

Upvotes: 0

Views: 967

Answers (1)

Derlin
Derlin

Reputation: 9881

with cstrings, the operator << will read a string and append the null-byte character automatically at the end of the buffer if there is enough space.

you allocate a buffer of 11, so when the password entered is higher than 10, the null byte terminating the string won't be present, causing problems with strlen and such. Indeed, what strlen does is simply reading the input and incrementing a counter until a \0 is encountered.

You have now two choices:

  1. keep going with cstring and augment the size of the buffer (high enough to avoid surprises),
  2. switch to the string class of c++, which is an array of char able to increase dynamically (strongly recommended, here is a link to get started).

Also, concerning the code: you have a lot of unnecessary stuff. For example:

do
{
    while (!validatePassword(password))     //if the functions returns a false value
    {
        cout << "\nYour password does not meet the requirements. ";
        cout << "\nEnter a new password: ";
        cin >> password;
        size = strlen(password);
    }
} while (size > 10);

if (validatePassword(password))
{
    cout << "\nYour password " << password << " meets the requirements. \n";    //if the function returns a true value

}

could be replaced by:

while (!validatePassword(password))
{
   cout << "\nYour password does not meet the requirements. ";
   cout << "\nEnter a new password: ";
   cin >> password;
}
cout << "\nYour password " << password << " meets the requirements. \n"; 

validatePassword calls validateLength which checks that strlen(pass) <= 10 and you can exit the first loop only when the password is correct.

Another improvement would be to pass along the size of the password to your functions in order to avoid calling strlen everywhere (it is common in C to always pass the size with a char * argument).

Upvotes: 2

Related Questions