-1

Essentially, I wrote a rather small random character generator, where the user can pick the length of the character string. The program can successfully create a string of length 2,077,072, but crashes with a stack overflow at one greater than that.

This number seems rather arbitrary, since log2(thatNumber) equals around 20.9. It's too small to exceed two mebibytes, and both 16-bit and 32-bit sizes are nowhere near. Why is it breaking here, of all places?

The program executes at least as far as the "Processing..." marker.

My code:

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

char getChar(int, int, int);

//MAXIMUM PASSWORD LENGTH: 2,077,072
//2,077,073 gives stack overflow

int main(int argc, char **argv) {
    if(argc != 5) {
        printf("Incorrect number of arguments.\n Usage: PassGenII arg1 arg2 arg3 arg4\n");
        printf("arg1: Password length\narg2: Use lowercase characters? 0 or 1\narg3 Use uppercase characters? 0 or 1\narg4: Use numeric characters? 0 or 1\n");
        return 0;
    } else {
        int passLength;
        int lower;
        int upper;
        int numeric;

        passLength = atoi(argv[1]);
        lower = atoi(argv[2]);
        upper = atoi(argv[3]);
        numeric = atoi(argv[4]);

        printf("\nPassword length: %d\n", passLength);
        printf("lowercase: %d\n", lower);
        printf("uppercase: %d\n", upper);
        printf("numerals: %d\n", numeric);
        printf("\nProcessing...");
        char pass[passLength];

        srand(time(NULL));
        int i;
        for(i = 0; i < passLength; i++) {
            pass[i] = getChar(lower, upper, numeric);
        }


        FILE *fp = fopen("C:/PassGen/password.txt", "w");
        for(i = 0; i < passLength; i++) {
            putc(pass[i], fp);
        }
        fclose(fp);

        printf("\n\nSuccessful! The password is in a text file\nin C:/PassGen/\n");

        return 0;
    }
}

char getChar(int lower, int upper, int numeric) {
    int rand1;
    int fail;
    char passChar;

    do {
        fail = 0;
        rand1 = rand() % 3;

        switch(rand1) {
            case 0:
                if(lower) {
                    passChar = rand() % 26 + 97;
                } else {
                    fail = 1;
                }
                break;
            case 1:
                if(upper) {
                    passChar = rand() % 26 + 65;
                } else {
                    fail = 1;
                }
                break;
            case 2:
                if(numeric) {
                    passChar = rand() % 10 + 48;
                } else {
                    fail = 1;
                }
                break;
        }
    } while(fail);

    return passChar;
}
JoeReaper
  • 11
  • 1
  • You are creating an array of 2MB on the stack. That's a lot. Use dynamic allocation on the heap via `malloc` (and `free` later) for arbitrarily large arrays. – M Oehm Mar 12 '16 at 05:15
  • That solved it! I did it a little differently by removing the array altogether. I'll post the result in a bit – JoeReaper Mar 12 '16 at 05:27
  • Yes, of course, if you are just generating a string of random characters that don't require information of previous characters, you can print the result right away. That's a better solution. – M Oehm Mar 12 '16 at 05:31

2 Answers2

1

char pass[passLength]; This statement is creating problem if your passLength is huge number. It is never a good practice to declare huge array.

Do not declare huge arrays to avoid buffer overflow. Use malloc instead to allocate huge memory.

You may refer this How many chars can be in a char array?

Community
  • 1
  • 1
Rocoder
  • 1,083
  • 2
  • 15
  • 26
0

Thanks to @MOehm, I was able to modify the code to remove this limit. The new limit is now (2^32)/2 - 1, or 2,147,483,647. This makes much more sense, and is also much larger than before.

I could theoretically extend this limit even farther by using a larger variable type than int for the variable passLength, but I don't have any real reason to (and also I'll probably wind up having a .txt file taking up my entire hard drive if I did).

The modified bit of code:

FILE *fp = fopen("C:/PassGen/password.txt", "w");

int i;
for(i = 0; i < passLength; i++) {
    putc(getChar(lower, upper, numeric), fp);
}

fclose(fp);

I essentially removed the array that was storing the characters altogether and instead chose to write the characters directly on to the .txt file

JoeReaper
  • 11
  • 1