REALLOC()可能的泄漏:当Realloc()在分配内存时失败时,原始指针会丢失

发布于 2025-02-03 03:16:55 字数 4335 浏览 4 评论 0原文

我知道这已经很多次了,但似乎每次都发生了这个问题的发生略有不同。

我有以下C应用程序,该应用程序从称为word_generator()的函数接收一个字符串,然后对每个传入的字符串进行过滤,并且一旦满足条件,则将当前字符串存储在char数组中,称为<代码> output_char_buffer 。

由于传入数据具有可变长度,因此需要动态调整该过程中涉及的字符阵列。

该应用程序似乎正在起作用,但是静态分析工具正在抱怨以下消息:

warning: V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'output_char_buffer' is lost.
Consider assigning realloc() to a temporary pointer.

这是代码:

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

char *word_generator(int selector)
{
    switch(selector)
    {
        case 0:
            return "gpu-log-02_05_2022_12_37_56_784";
            break;
        case 1:
            return "glsl-debug.txt";
            break;
        case 2:
            return "compiler.log";
            break;
        case 3:
            return "shader.pub";
            break;
        case 4:
            return "fluid-sim-variantA.cache";
            break;
        default:
            printf("ERROR: Request out of range!\n");
    }
    return "";
}


int main() {

    char *output_char_buffer;
    output_char_buffer = NULL;

    // Simulate incoming data.
    for (int i = 0; i < 5; i++)
    {
        printf("Test string[%d]: %s\n", i, word_generator(i));
        
        unsigned long local_buffer_length = strlen(word_generator(i));
        unsigned long input_buffer_length = 0;

        char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
        
        if (input_char_buffer != NULL)
        {
            strcpy(input_char_buffer, word_generator(i));
            input_buffer_length = strlen(input_char_buffer);
        }
        else
        {
            // Clean-up.
            free(input_char_buffer);
            input_char_buffer = NULL;

            printf("ERROR: Failed to allocate char buffer memory!\n");

            // Exit with an error state.
            return 1;
        }
        
        // Verbose debug.
        printf("\tCurrent input buffer (value: %s, length: %lu)\n", input_char_buffer, input_buffer_length);
        
        char key[] = "compiler.log";
        
        // Verbose debug.
        printf("\tCurrent key (value: %s, length: %lu)\n", key, strlen(key));

        if (strcmp(input_char_buffer, key) == 0)
        {
            printf("\t\t__MATCH__\n");
            
            output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
            
            if (output_char_buffer != NULL)
            {
                strcpy(output_char_buffer, input_char_buffer);
            }
            else
            {
                // Clean-up.
                free(output_char_buffer);
                output_char_buffer = NULL;
                
                printf("ERROR: Failed to fetch char buffer memory!\n");
                
                // Exit with an error state.
                return 1;
            }
        }

        // Clean-up.
        free(input_char_buffer);
        input_char_buffer = NULL;
    }

    // Check the final value of the string container.
    printf("Result: %s\n", output_char_buffer);
    
    // Clean-up and finish.
    free(output_char_buffer);
    output_char_buffer = NULL;
    
    return 0;
}

输出:

Test string[0]: gpu-log-02_05_2022_12_37_56_784
        Current input buffer (value: gpu-log-02_05_2022_12_37_56_784, length: 31)
        Current key (value: compiler.log, length: 12)
Test string[1]: glsl-debug.txt
        Current input buffer (value: glsl-debug.txt, length: 14)
        Current key (value: compiler.log, length: 12)
Test string[2]: compiler.log
        Current input buffer (value: compiler.log, length: 12)
        Current key (value: compiler.log, length: 12)
                __MATCH__
Test string[3]: shader.pub
        Current input buffer (value: shader.pub, length: 10)
        Current key (value: compiler.log, length: 12)
Test string[4]: fluid-sim-variantA.cache
        Current input buffer (value: fluid-sim-variantA.cache, length: 24)
        Current key (value: compiler.log, length: 12)
Result: compiler.log

该问题标记的行是:

output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));

解决此问题的安全方法是什么?

I know this has been asked many many times, but it seems like the occurrence of this issue is slightly different every time.

I have the following C application, that receives a string from a function called word_generator(), then every incoming string is filtered and once the condition is met, the current string is stored in a char array called output_char_buffer.

Since the incoming data has a variable length, the char arrays involved in the process needs to be dynamically resized.

The application seems to be working, but the static analysis tool is complaining with the following message:

warning: V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'output_char_buffer' is lost.
Consider assigning realloc() to a temporary pointer.

Here is the code:

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

char *word_generator(int selector)
{
    switch(selector)
    {
        case 0:
            return "gpu-log-02_05_2022_12_37_56_784";
            break;
        case 1:
            return "glsl-debug.txt";
            break;
        case 2:
            return "compiler.log";
            break;
        case 3:
            return "shader.pub";
            break;
        case 4:
            return "fluid-sim-variantA.cache";
            break;
        default:
            printf("ERROR: Request out of range!\n");
    }
    return "";
}


int main() {

    char *output_char_buffer;
    output_char_buffer = NULL;

    // Simulate incoming data.
    for (int i = 0; i < 5; i++)
    {
        printf("Test string[%d]: %s\n", i, word_generator(i));
        
        unsigned long local_buffer_length = strlen(word_generator(i));
        unsigned long input_buffer_length = 0;

        char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
        
        if (input_char_buffer != NULL)
        {
            strcpy(input_char_buffer, word_generator(i));
            input_buffer_length = strlen(input_char_buffer);
        }
        else
        {
            // Clean-up.
            free(input_char_buffer);
            input_char_buffer = NULL;

            printf("ERROR: Failed to allocate char buffer memory!\n");

            // Exit with an error state.
            return 1;
        }
        
        // Verbose debug.
        printf("\tCurrent input buffer (value: %s, length: %lu)\n", input_char_buffer, input_buffer_length);
        
        char key[] = "compiler.log";
        
        // Verbose debug.
        printf("\tCurrent key (value: %s, length: %lu)\n", key, strlen(key));

        if (strcmp(input_char_buffer, key) == 0)
        {
            printf("\t\t__MATCH__\n");
            
            output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
            
            if (output_char_buffer != NULL)
            {
                strcpy(output_char_buffer, input_char_buffer);
            }
            else
            {
                // Clean-up.
                free(output_char_buffer);
                output_char_buffer = NULL;
                
                printf("ERROR: Failed to fetch char buffer memory!\n");
                
                // Exit with an error state.
                return 1;
            }
        }

        // Clean-up.
        free(input_char_buffer);
        input_char_buffer = NULL;
    }

    // Check the final value of the string container.
    printf("Result: %s\n", output_char_buffer);
    
    // Clean-up and finish.
    free(output_char_buffer);
    output_char_buffer = NULL;
    
    return 0;
}

Output:

Test string[0]: gpu-log-02_05_2022_12_37_56_784
        Current input buffer (value: gpu-log-02_05_2022_12_37_56_784, length: 31)
        Current key (value: compiler.log, length: 12)
Test string[1]: glsl-debug.txt
        Current input buffer (value: glsl-debug.txt, length: 14)
        Current key (value: compiler.log, length: 12)
Test string[2]: compiler.log
        Current input buffer (value: compiler.log, length: 12)
        Current key (value: compiler.log, length: 12)
                __MATCH__
Test string[3]: shader.pub
        Current input buffer (value: shader.pub, length: 10)
        Current key (value: compiler.log, length: 12)
Test string[4]: fluid-sim-variantA.cache
        Current input buffer (value: fluid-sim-variantA.cache, length: 24)
        Current key (value: compiler.log, length: 12)
Result: compiler.log

The line flagged for the issue is this one:

output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));

What would be the safe way to handle this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

荒芜了季节 2025-02-10 03:16:55

代码中有2个实例realloc。在第二个中,原始指针确实被覆盖:

output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));

您应该将返回值存储到临时变量中,以便在失败的情况下释放原始指针,从而避免内存泄漏。

还要注意,代码中的清理不完整:您应该释放input_char_bufferoutput_char_buffer,以防万一在上一次迭代中分配了。

这是一个修改版本:

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

const char *word_generator(int selector) {
    switch (selector) {
    case 0:  return "gpu-log-02_05_2022_12_37_56_784";
    case 1:  return "glsl-debug.txt";
    case 2:  return "compiler.log";
    case 3:  return "shader.pub";
    case 4:  return "fluid-sim-variantA.cache";
    default: printf("ERROR: Request out of range!\n");
             return "";
    }
}

int main() {
    char *output_char_buffer = NULL;

    // Simulate incoming data.
    for (int i = 0; i < 5; i++) {
        const char *word = word_generator(i);
        printf("Test string[%d]: %s\n", i, word);

        size_t local_buffer_length = strlen(word);

        char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
        if (input_char_buffer == NULL) {
            // Clean-up.
            free(output_char_buffer);
            output_char_buffer = NULL;

            printf("ERROR: Failed to allocate char buffer memory!\n");
            // Exit with an error state.
            return 1;
        }

        strcpy(input_char_buffer, word);
        size_t input_buffer_length = strlen(input_char_buffer);

        // Verbose debug.
        printf("\tCurrent input buffer (value: %s, length: %zu)\n",
               input_char_buffer, input_buffer_length);

        char key[] = "compiler.log";

        // Verbose debug.
        printf("\tCurrent key (value: %s, length: %zu)\n", key, strlen(key));

        if (strcmp(input_char_buffer, key) == 0) {
            printf("\t\t__MATCH__\n");

            char *temp = (char *)realloc(output_char_buffer, local_buffer_length + 1);
            if (temp == NULL) {
                // Clean-up.
                free(output_char_buffer);
                output_char_buffer = NULL;
                free(input_char_buffer);
                input_char_buffer = NULL;

                printf("ERROR: Failed to fetch char buffer memory!\n");

                // Exit with an error state.
                return 1;
            }
            output_char_buffer = temp;
            strcpy(output_char_buffer, input_char_buffer);
        }

        // Clean-up.
        free(input_char_buffer);
        input_char_buffer = NULL;
    }

    // Check the final value of the string container.
    printf("Result: %s\n", output_char_buffer);

    // Clean-up and finish.
    free(output_char_buffer);
    output_char_buffer = NULL;
    return 0;
}

There are 2 instances of realloc in the code. In the second one, the original pointer is indeed overwritten:

output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));

You should instead store the return value into a temporary variable so you can free the original pointer in case of failure, thus avoiding a memory leak.

Also note that the cleanup in your code is incomplete: you should free both the input_char_buffer and the output_char_buffer in case it has been allocated during a previous iteration.

Here is a modified version:

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

const char *word_generator(int selector) {
    switch (selector) {
    case 0:  return "gpu-log-02_05_2022_12_37_56_784";
    case 1:  return "glsl-debug.txt";
    case 2:  return "compiler.log";
    case 3:  return "shader.pub";
    case 4:  return "fluid-sim-variantA.cache";
    default: printf("ERROR: Request out of range!\n");
             return "";
    }
}

int main() {
    char *output_char_buffer = NULL;

    // Simulate incoming data.
    for (int i = 0; i < 5; i++) {
        const char *word = word_generator(i);
        printf("Test string[%d]: %s\n", i, word);

        size_t local_buffer_length = strlen(word);

        char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
        if (input_char_buffer == NULL) {
            // Clean-up.
            free(output_char_buffer);
            output_char_buffer = NULL;

            printf("ERROR: Failed to allocate char buffer memory!\n");
            // Exit with an error state.
            return 1;
        }

        strcpy(input_char_buffer, word);
        size_t input_buffer_length = strlen(input_char_buffer);

        // Verbose debug.
        printf("\tCurrent input buffer (value: %s, length: %zu)\n",
               input_char_buffer, input_buffer_length);

        char key[] = "compiler.log";

        // Verbose debug.
        printf("\tCurrent key (value: %s, length: %zu)\n", key, strlen(key));

        if (strcmp(input_char_buffer, key) == 0) {
            printf("\t\t__MATCH__\n");

            char *temp = (char *)realloc(output_char_buffer, local_buffer_length + 1);
            if (temp == NULL) {
                // Clean-up.
                free(output_char_buffer);
                output_char_buffer = NULL;
                free(input_char_buffer);
                input_char_buffer = NULL;

                printf("ERROR: Failed to fetch char buffer memory!\n");

                // Exit with an error state.
                return 1;
            }
            output_char_buffer = temp;
            strcpy(output_char_buffer, input_char_buffer);
        }

        // Clean-up.
        free(input_char_buffer);
        input_char_buffer = NULL;
    }

    // Check the final value of the string container.
    printf("Result: %s\n", output_char_buffer);

    // Clean-up and finish.
    free(output_char_buffer);
    output_char_buffer = NULL;
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文