-3

I am working on a project and I have to increase the size of an array or it prints garbage.

This variable is declared in main

char *fullPath[150];

Then I ask a user a question using this

printf("Enter full path where you want the file to be.\nExample: C:\\Windows\\System32\n");
scanf("%s", &fullPath);

Then I check that this directory exists using

CheckDirectory(fullPath);

Which is my function that looks like...

void CheckDirectory(char *d) {
    DIR* dir = opendir(d);
    char answer[2];

    if (dir) {
        printf("Directory Exists!\n");
        closedir(dir);
    } else if (ENOENT == errno) {
        printf("Directory does not exist.\n");
        printf("Do you want to create this directory? y/n:");
        scanf("%s", &answer);
        if (strcmp(answer, "y") == 0) {
            printf("Ok creating directory\n");
            MakeDirectory(d);
        } else {
            printf("ok not gonna make it");
            exit(1);
        }
    } else {
        printf("Some magical error.");
    }
}

So the above code just basically asks a user for a directory and then puts it into fullPath[150] and then runs tests on it. The next part of the script which is where I run into errors is..

CopyNewFile(fullPath, fileName, argv[0]);

An the function looks like..

void CopyNewFile(char *dir, char *fname, char *curName) {
    char fullDir[350];
    char file[60];

    strncat(file, curName, 20);
    strncat(file, ".exe", 5);
    strncat(fullDir, dir, 250);
    strncat(fullDir, "\\", 5);
    strncat(fullDir, fname, 30);
    if (CopyFile(file, fullDir, FALSE)) {
        printf("\n\nCopied new file.\n\n");
    } else {
        printf("Did not copy.");
    };
}

Now, here is the issue. When I try to run this, it won't copy unless

char fullDir[350];

Is more than 300. I tried 350 and it works, but I haven't tested to find the exact number where it does and does not work. If I it 300, then the fullDir and file gets garbage characters in front of it.

I assume it is something to do with the way memory is allocated but instead of increasing the size of the character arrays I would like to fix it.

Brian Jarcus
  • 69
  • 1
  • 1
  • 6
  • Why do you have an array of 150 strings instead of a string of 150 characters? Check your compiler warnings... – Davis Herring Jan 19 '18 at 15:00
  • 2
    `char *fullPath[150];` -> `char fullPath[150];`. – Lundin Jan 19 '18 at 15:04
  • regarding: `char *fullPath[150];` This is declaring an array of 150 pointers to char, not an array of char that can contain 150 characters. Suggest: `char fullPath[150];` – user3629249 Jan 19 '18 at 15:24
  • regarding: `scanf("%s", &fullPath);` 1) when calling any of the `scanf()` family of functions, always check the returned value (not the parameter values) to assure the operation was successful. 2) when using the '%s' or '%[...]format specifiers, always include a MAX CHARACTERS modifier that one less than the length of the input buffer to avoid any buffer overflow and resulting undefined behavior. 3) in C, an array name degrades to the address of the first byte of the array. Suggest: `scanf("%149s", fullPath);` – user3629249 Jan 19 '18 at 15:31
  • regarding: `char answer[2];` and `scanf("%s", &answer);` Remembering my (above) comments, the result of these two statements is undefined behavior. written correctly, the code would be `scanf("%1s", answer);` or better yet: `char answer;` and `scanf( "%c", &answer );` – user3629249 Jan 19 '18 at 15:40
  • regarding: `CopyNewFile(fullPath, fileName, argv[0]);` `argv[0]` is a pointer to a char array that contains name of the currently executing file. Perhaps you meant: `CopyNewFile(fullPath, fileName, argv[1]);` – user3629249 Jan 19 '18 at 15:44
  • please post a [mcve] so we can reproduce the problem. – user3629249 Jan 19 '18 at 15:46
  • regarding: `printf("Some magical error.");` Error messages should be output to `stderr`, not `stdout` And when the error indication comes from a C library function, call `perror()` so both the text and the reason the system thinks the error occurred are output to `stderr` – user3629249 Jan 19 '18 at 15:49
  • regarding: `strncat(file, curName, 20);` and `strncat(fullDir, dir, 250);` The `strncat()` function starts appending where it finds a NUL byte. The arrays on the stack are not initialized, so contain what ever trash happens to be on the stack at their location. Suggest the first assignment for each array use `strcpy()` rather than `strncat()`. – user3629249 Jan 19 '18 at 15:53

2 Answers2

1
char *fullPath[150];

declares 150 pointers of char *. You need

char fullPath[150];

then

scanf("%149s", fullPath);

or you're passing the wrong pointer type to scanf.

(note the lack of & and the size limiter to avoid buffer overflow when entering the path)

The next error (as seen in comments), which (now I realize) is probably the one which triggers the symptoms you're getting:

char file[60];
strncat(file, curName, 20);

that is plain wrong (same for fullDir) because file isn't initialized. One quickfix would be:

char file[60];

But as mentionned with Lundin in comments, it's better to avoid strncat altogether) You could replace the whole strncat block by:

sprintf(file,"%55s.exe",curName);
sprintf(fullDir, "\\%347s", fname);

(trying to compute the max amounts of chars to avoid overflow there also)

or a more classical approach using first strcpy then strcat (no length checking though)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • Thank you. I went through and fixed that and it still produces garbage in front of the directory and filename. – Brian Jarcus Jan 19 '18 at 15:08
  • 1
    @BrianJarcus Because you can't use strcat/strncat on a buffer which is not initialized. It expects a proper string as parameter, not an uninitialized pointer. In addition, `strncat` is one of those functions that [should never be used](https://stackoverflow.com/a/46563868/584518). – Lundin Jan 19 '18 at 15:10
  • Ah ok. So using just char file[60]; isn't the same as doing something like char file[60] = "";? I am still learning. Also on the last post for replacing the strncat block, I still need to cat the file name to the end of the fullDir. – Brian Jarcus Jan 19 '18 at 15:24
  • Use `strcpy` for the first string and then `strcat` (note the lack of n) for the rest – Chris Turner Jan 19 '18 at 15:26
  • @ChrisTurner yes, that works, but I like the `sprintf` approach better because 1) one line and 2) cheap length checking – Jean-François Fabre Jan 19 '18 at 15:31
  • @BrianJarcus: yes adding `= ""` would have fixed it as well (see my edit) – Jean-François Fabre Jan 19 '18 at 15:32
  • Awesome. I took a look into sprintf and I like that. I ran into issues previously because I wasn't able to use the format options like %s. Now that I can do that with sprintf I can fix some code. It is all working now and it makes sense on what I am doing. Thank you for your help. – Brian Jarcus Jan 19 '18 at 15:36
  • @Jean-FrançoisFabre sorry - I should have tagged the OP in my comment as I was responding to their comment above mine – Chris Turner Jan 19 '18 at 15:39
  • @ChrisTurner no sweat. answers like this need to be super-complete, otherwise it's not very useful – Jean-François Fabre Jan 19 '18 at 16:05
1

You never initialized the variable file before you concatenate to it. Change it like this. Same with fullDir.

char file[60] = {0};

strncat(file, curName, 20);
cleblanc
  • 3,678
  • 1
  • 13
  • 16
  • So would char file[60] just be declaring it? And then assigning something to it be initializing? Thanks for your help. – Brian Jarcus Jan 19 '18 at 15:25
  • @BrianJarcus yes that's correct. When you declare something without initialization it may contain any value. – cleblanc Jan 19 '18 at 15:26