Home > Back-end >  is it safe to make a VLA slightly longer than argv[1]?
is it safe to make a VLA slightly longer than argv[1]?

Time:05-30

Example code, treats argv[1] as a file path, replacing its extension with .png or appending it if none is found:

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

int main(int argc, char **argv) {
    if (argc != 2)
        return 1;

    char *lastdot = strrchr(argv[1], '.');
    size_t len = lastdot ? (lastdot - argv[1]) : strlen(argv[1]);

    char outpath[len   sizeof(".png")];
    // ^ this is the important part

    memcpy(outpath, argv[1], len);
    memcpy(outpath   len, ".png", sizeof(".png"));

    printf("%s\n", outpath);
}

My main concern here is that argv[1] may be just small enough to not cause an error from the OS itself, but then the extra 4 bytes added by the ".png" concatenation will cause a stack overflow when allocating the VLA?

The problem is that I'm not really sure how the sizes of either a member of argv or a VLA are limited.

Apparently constants such as PATH_MAX aren't to be trusted for static array sizes, so it's either this or malloc.

CodePudding user response:

Your concern is genuine: nothing in the C Standard guarantees that the stack space available to your program will be sufficient to allocate a large VLA for a very long command line argument plus 4 bytes. In practice, on modern operating systems, the stack space is typically at least 1 megabyte and command line arguments are limited to about 100 KB... so you should be safe.

Also beware that some compilers do not support VLAs at all, so allocating from the heap is a more portable approach.

Incidentally, you can modify your program to avoid this issue completely:

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

int main(int argc, char *argv[]) {
    if (argc != 2)
        return 1;

    char *lastdot = strrchr(argv[1], '.');
    int len = lastdot ? lastdot - argv[1] : strlen(argv[1]);

    printf("%.*s.png\n", len, outpath);
    return 0;
}
  • Related