简体   繁体   English

C6386 - 使用 fread() 函数写入“缓冲​​区”时缓冲区溢出

[英]C6386 - Buffer overrun while writing to 'buffer' when using fread() function

"Warning C6386 Buffer overrun while writing to 'buffer': the writable size is ' Param (1)* Param (2)' bytes, but '4294967295' bytes might be written." “警告 C6386 在写入 'buffer' 时缓冲区溢出:可写大小为 ' Param (1)* Param (2)' 字节,但可能会写入 '4294967295' 字节。”

I'm writing a code to calculate a postfix expression using a stack implemented using linked lists, and I'm reading the postfix expression from a local file in binary ( fopen(filename, "rb" ) into a buffer. I get the above mentioned warning at this line of code:我正在编写代码来使用使用链表实现的堆栈来计算后缀表达式,并且我正在从二进制本地文件( fopen(filename, "rb" )中读取后缀表达式到缓冲区中。我得到了上述内容在这行代码中提到警告:

fread(buffer, sizeof(char), fileLength, file);

But, I've used calloc to allocate exactly the amount of memory I'd need based on the length of the file like this:但是,我已经使用 calloc 根据文件的长度准确分配了我需要的内存量,如下所示:

fseek(file, 0, SEEK_END);
fileLength = ftell(file);

buffer = (char*)calloc(fileLength + 1, sizeof(char));
if (!buffer) {
    perror("Can't allocate memory!\n");
    return NULL;
}

I don't understand where it got the " '4294967295' bytes might be written ".我不明白它在哪里得到“ '4294967295'字节可能被写入”。 Anyone care enough to explain what might be the cause, I'm a student and I'm not that much experienced with C.任何人都足够关心解释可能是什么原因,我是一名学生,我对 C 的经验并不多。

Here's the entire function block:这是整个功能块:

int CalculatePostfix(double* destination, char* fileName)
{
    FILE* file = NULL;
    int fileLength = 0;
    char* buffer = NULL;
    char* currentBuffer = NULL;
    int numBytes = 0;
    char operation = 0;
    double number = 0;
    int status = EXIT_SUCCESS;;
    StackElement head = { .number = 0, .next = NULL };

    file = fopen(fileName, "rb");
    if (!file) {
        perror("Can't open file!\n");
        return -1;
    }

    fseek(file, 0, SEEK_END);
    fileLength = ftell(file);

    buffer = (char*)calloc(fileLength + 1, sizeof(char));
    if (!buffer) {
        perror("Can't allocate memory!\n");
        return NULL;
    }

    rewind(file);
    fread(buffer, sizeof(char), fileLength, file);
    printf("|%s|\n", buffer);
    fclose(file);

    currentBuffer = buffer;
    while (strlen(currentBuffer) > 0) {
        status = sscanf(currentBuffer, " %lf %n", &number, &numBytes);

        if (status == 1) {
            Push(&head, number);
            currentBuffer += numBytes;
        }
        else {
            sscanf(currentBuffer, " %c %n", &operation, &numBytes);
            status = PerformOperation(&head, operation);

            if (status != EXIT_SUCCESS) {
                free(buffer);
                while (head.next != NULL) {
                    DeleteAfter(&head);
                }
                return -1;
            }
            currentBuffer += numBytes;
        }
    }

    free(buffer);
    return EXIT_SUCCESS;
}

ftell returns a long integer, fread takes a size_t which, depending on implementation, often is an unsigned int. ftell 返回一个长整数,fread 接受一个 size_t,根据实现,它通常是一个无符号整数。 So if you happen to get -1L (which is the error return code from ftell) back from ftell you will end up vid a massive large unsigned int.所以如果你碰巧从 ftell 得到 -1L(这是来自 ftell 的错误返回码),你最终会得到一个巨大的无符号整数。

So to solve this, check return value of ftell and make sure it is not -1L, then when calling fread cast to size_t所以要解决这个问题,检查 ftell 的返回值并确保它不是 -1L,然后在调用 fread cast to size_t 时

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM