检查输入字符串是否超出缓冲区限制(崩溃)

时间:2017-04-28 15:21:15

标签: c string memory buffer

我正在创建一个将目录路径作为参数传递的函数,或者如果它保留为空,则提示用户输入。

我已设置PATH_MAX=100if语句以检查if ((strlen(folder path) + strlen(file path)) > PATH_MAX)是否会要求用户再次输入。

但是,当我检查所有条件是否有效时(设置PATH_MAX=20),如果folder path自身超过PATH_MAX,则缓冲区因大小不足而崩溃(L'Buffer is too small' &&0

有没有办法检查用户是否事先超过PATH_MAX并告知路径太长,以避免崩溃缓冲区?或者我应该增加PATH_MAX的大小?

代码:

#define PATH_MAX 100
void CreateFiles(char folder[PATH_MAX])
{
    char addrbook[PATH_MAX] = "caf-sorted.txt";
    char path[PATH_MAX]="";

    if ((strlen(folder)<4)) 
    {
        //User inputs directory
        printf("Enter New Directory\n(!Do not enter filename!)\n");

        if (NULL == fgets(path, sizeof path, stdin))
        {//check if fgets fails
            if (ferror(stdin))
            {
                folder="";
                perror("fgets() failed");
                CreateFiles(folder);
                return;
            }
        }
    }
    else
        memcpy(path, folder, strlen(folder));

    path[strcspn(path, "\n\r")] = 0;

    if (strlen(addrbook) > 0 && '\\' != path[strlen(path) - 1])
    {
        if (PATH_MAX < strlen(path))
        {
            errno = EINVAL;
            perror("'path' too long");
            folder="";
            CreateFiles(folder);
            return;
        }

        strcat(path, "\\");
    }

    if (PATH_MAX < (strlen(path) + strlen(addrbook)))
    {
        errno = EINVAL;
        perror("'path\\filename' too long");
        folder="";
        CreateFiles(folder);
        return;
    }
}

1 个答案:

答案 0 :(得分:2)

您必须考虑终止空字符

if (!(strlen(path) < PATH_MAX))

确保路径中的字符数(不带空字符)始终至少比PATH_MAX小一个,这为终止空字符留下了空间。

你必须考虑到你使用的每个C字符串,因为strlen(char * string)总是比你需要存储字符串所需的空间少一个,如果你想能够终止它。 / p>

编辑:所以我至少研究了你函数的前几行,并尝试快速重新实现它们。它不漂亮,但它有效:

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

#define PATH_MAX 100

void create_files (char *folder)
{
    char addr_book[] = "caf-sorted.txt";
    char path[PATH_MAX];


    // Setting all bytes in *path to zero
    bzero(path, PATH_MAX);



    // If the folder name is too short, we ask for a new one
    if (strlen(folder) < 4) {

        char c; // This will store our input from stdin, one char at a time



        // As long as the supplied path name is too short, we'll keep asking:

        while (strlen(path) < 4) {
            printf("Please enter a path (no filename!): ");


            // We get one character at a time from stdin using getc(...):
            // until we encounter a newline

            for (int i = 0; (c = getc(stdin)) != '\n'; i++) {

                if (i < PATH_MAX - 1) {

                    // As long as we have space for two more characters
                    // (the value of c plus a null character after it)
                    // We'll keep appending c:

                    path[i] = c;

                } else if (i == PATH_MAX - 1) {

                    // If we get too many characters from stdin, we
                    // display an error message and reset our path to
                    // all null characters again, so the outermost loop
                    // will run again

                    fprintf(stderr, "Path is too long!\n");
                    bzero(path, PATH_MAX);

                    // Notice that we do not have a break statement
                    // here, we iterate through the input string from
                    // stdin until we encounter a newline character,
                    // so we don't have any superfluous characters
                    // that spill into the beginning ouf our freshly
                    // reset path string
                }
            }
        }
    } else {
        // Or, you know, if the programmer specifies a proper value,
        // Just do it the easy way and copy that into our path string
        // (although this will truncate a folder name that is too long):

        strncpy(path, folder, PATH_MAX - 1);
    }
}

int main ()
{
    create_files("");

    return 0;
}