由单线引起的堆缓冲区溢出

发布于 2025-02-13 19:02:54 字数 1226 浏览 3 评论 0原文

目前正在尝试通过做一些LeetCode问题来处理我的C(非常新的)。我对这个问题感到困惑,因为它给了我堆的缓冲区溢出,但仅由于一行。 drigens()被调用并传递了字符串命令其中1< = command.length< = 100,将由“ g” ,“()”和/或“(al)”在某些顺序上,没有其他字符出现。

char * interpret(char * command){
    
    char * ret = malloc(sizeof(char) * 100);
    int counter = 0;
    for(int i = 0; i < sizeof(command) - 1; i++)
    {
        if(command[i] == 'G')
        {
            ret[counter] = 'G';
            counter ++;
        }
        else if(command[i] == '(')
        {
            if (command[i + 1] == ')')
            {
                ret[counter] = 'o';
                counter ++;
            }
            else
            {
                //ret[counter] = 'a'; ***********
                ret[counter + 1] = 'l';
                counter += 2;
            }
        }
        ret[counter] = '\0';
    }
    return realloc(ret, counter * sizeof(char));
}

如果标明的行是未注册的,则整个程序在Leetcode中崩溃,但在VSCODE上工作正常并返回正确的解决方案。我会感谢任何帮助,我敢肯定这是我缺少的小东西。谢谢。

eta:这是所讨论的leetcode问题

Currently trying to work on my C (very new to it) by doing some leetcode questions. I'm puzzled by this issue, as it gives me a heap buffer overflow but only because of a single line. interpret() is called and passed a string command where 1 <= command.length <= 100, and will consist of "G", "()", and/or "(al)" in some order, with no other characters appearing.

char * interpret(char * command){
    
    char * ret = malloc(sizeof(char) * 100);
    int counter = 0;
    for(int i = 0; i < sizeof(command) - 1; i++)
    {
        if(command[i] == 'G')
        {
            ret[counter] = 'G';
            counter ++;
        }
        else if(command[i] == '(')
        {
            if (command[i + 1] == ')')
            {
                ret[counter] = 'o';
                counter ++;
            }
            else
            {
                //ret[counter] = 'a'; ***********
                ret[counter + 1] = 'l';
                counter += 2;
            }
        }
        ret[counter] = '\0';
    }
    return realloc(ret, counter * sizeof(char));
}

If the starred line is uncommented, then the entire program crashes in leetcode, but works fine on VSCode and returns the correct solution. I would appreciate any help, I'm sure it's something small I'm missing. Thanks.

ETA: Here is the leetcode problem in question

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

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

发布评论

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

评论(2

小草泠泠 2025-02-20 19:02:54

参数命令具有指针类型char *

因此,应用于指针的操作员sizeof可产生指针的大小,而不是尖字符串的长度,

for(int i = 0; i < sizeof(command) - 1; i++)

您可以写入

for( size_t i = 0; command[i] != '\0'; i++)

尖头的长度,也不清楚为什么使用魔术数字100

char * ret = malloc(sizeof(char) * 100);

您可以首先计数结果字符,然后分配适当大小的数组并填充它。

此外,由于此语句

    ret[counter] = '\0';

(这也不清楚为什么在for循环中)您需要使用counter + 1字符而不是counter字符分配一个数组 采用

return realloc(ret, counter * sizeof(char));

如下演示程序所示,

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

char * interpret( const char *command )
{
    size_t n = 0;

    for ( size_t i = 0; command[i] != '\0';  )
    {
        if ( command[i] == 'G' )
        {
            ++n;
            ++i;
        }
        else if ( strncmp( command + i, "()", 2 ) == 0 )
        {
            ++n;
            i += 2;
        }
        else if (  strncmp( command + i, "(al)", 4 ) == 0 )
        {
            n += 2;
            i += 4;
        }
        else
        {
            ++i;
        }
    }

    char *result = malloc( n + 1 );

    if ( result != NULL )
    {
        n = 0;

        for ( size_t i = 0; command[i] != '\0';  )
        {
            if ( command[i] == 'G' )
            {
                result[n++] = 'G';
                ++i;
            }
            else if ( strncmp( command + i, "()", 2 ) == 0 )
            {
                result[n++] = 'o';
                i += 2;
            }
            else if (  strncmp( command + i, "(al)", 4 ) == 0 )
            {
                result[n++] = 'a';
                result[n++] = 'l';
                i += 4;
            }
            else
            {
                ++i;
            }
        }

        result[n] = '\0';
    }

    return result;
}

int main( void )
{
    char *s = interpret( "G()(al)" );
    if ( s ) puts( s );
    free( s );

    s = interpret( "(al)G(al)()()G" );
    if ( s ) puts( s );
    free( s );
}

直接的方法可以看起来以下方式。程序输出是

Goal
alGalooG

The parameter command has the pointer type char *.

So the operator sizeof applied to the pointer yields the size of the pointer instead of the length of the pointed string

for(int i = 0; i < sizeof(command) - 1; i++)

You could just write

for( size_t i = 0; command[i] != '\0'; i++)

Also it is unclear why there is used the magic number 100

char * ret = malloc(sizeof(char) * 100);

You could at first count the result characters and then allocated an array of the appropriate size and fill it.

Moreover due to this statement

    ret[counter] = '\0';

(that is also unclear why it is within the for loop) you need to allocate an array with counter + 1 characters instead of counter characters as you are doing

return realloc(ret, counter * sizeof(char));

A straightforward approach can look the following way as shown in the demonstration program below.

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

char * interpret( const char *command )
{
    size_t n = 0;

    for ( size_t i = 0; command[i] != '\0';  )
    {
        if ( command[i] == 'G' )
        {
            ++n;
            ++i;
        }
        else if ( strncmp( command + i, "()", 2 ) == 0 )
        {
            ++n;
            i += 2;
        }
        else if (  strncmp( command + i, "(al)", 4 ) == 0 )
        {
            n += 2;
            i += 4;
        }
        else
        {
            ++i;
        }
    }

    char *result = malloc( n + 1 );

    if ( result != NULL )
    {
        n = 0;

        for ( size_t i = 0; command[i] != '\0';  )
        {
            if ( command[i] == 'G' )
            {
                result[n++] = 'G';
                ++i;
            }
            else if ( strncmp( command + i, "()", 2 ) == 0 )
            {
                result[n++] = 'o';
                i += 2;
            }
            else if (  strncmp( command + i, "(al)", 4 ) == 0 )
            {
                result[n++] = 'a';
                result[n++] = 'l';
                i += 4;
            }
            else
            {
                ++i;
            }
        }

        result[n] = '\0';
    }

    return result;
}

int main( void )
{
    char *s = interpret( "G()(al)" );
    if ( s ) puts( s );
    free( s );

    s = interpret( "(al)G(al)()()G" );
    if ( s ) puts( s );
    free( s );
}

The program output is

Goal
alGalooG
南七夏 2025-02-20 19:02:54

将命令的大小传递到解释。

在C中,当您将字符串传递给函数时,您实际上并没有传递完整的字符串,而是将指针传递给字符串中的第一个元素。当您进行大小(命令)时,这将成为一个问题,因为您只是获得指针的大小而不是完整的字符串。如果您尝试按照问题中完成的此字符串进行循环,则如果您的字符串长于sizeof(char*),或字符串短于sizeof(char*)。通常,您不应在指针上使用尺寸。

要修复您的代码,请在您传递给命令的字符串上使用strlen,并执行与此类似的操作:

char * interpret(char * command, int size){

char * ret = malloc(sizeof(char) * 100);
int counter = 0;
for(int i = 0; i < size; i++) 
{ ...

Pass the size of command to interpret.

In C, when you pass a string to a function, you’re not actually passing the full string, you’re passing a pointer to the first element in the string. This becomes an issue when you do sizeof(command), as you're just getting the size of the pointer and not the full string. If you try to loop over this string as done in the question, this can either lead to an underread, if you have a string longer than sizeof(char*), or a buffer overflow, if you have a string shorter than sizeof(char*). Generally, you shouldn’t use sizeof on pointers.

To fix your code, use strlen on the string you're passing to command in the calling function and do something similar to this:

char * interpret(char * command, int size){

char * ret = malloc(sizeof(char) * 100);
int counter = 0;
for(int i = 0; i < size; i++) 
{ ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文