Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When the length of the log content of the 'srs_error' level exceeds 4096, it will cause a memory overflow, leading to a stack corruption and a crash. #1229

Closed
dean-river opened this issue Sep 24, 2018 · 2 comments
Assignees
Labels
Bug It might be a bug. TransByAI Translated by AI/GPT.
Milestone

Comments

@dean-river
Copy link

dean-river commented Sep 24, 2018

The code is as follows:

void SrsFastLog::error(const char* tag, int context_id, const char* fmt, ...)
{
    if (_level > SrsLogLevel::Error) {
        return;
    }
    
    int size = 0;
    if (!generate_header(true, tag, context_id, "error", &size)) {
        return;
    }
    
    va_list ap;
    va_start(ap, fmt);
    // we reserved 1 bytes for the new line.
    size += vsnprintf(log_data + size, LOG_MAX_SIZE - size, fmt, ap);
    va_end(ap);

    // add strerror() to error msg.
    if (errno != 0) {
        size += snprintf(log_data + size, LOG_MAX_SIZE - size, "(%s)", strerror(errno));
    }

    write_log(fd, log_data, size, SrsLogLevel::Error);
}

Due to vsnprintf, when the content to be written is greater than LOG_MAX_SIZE - size, its return value is not the actual length written, but rather the length that should be written. The standard states it as follows:

If the resulting string would be longer than n-1 characters, 
the remaining characters are discarded and not stored, 
but counted for the value returned by the function.

So, when the content of the fmt, ap part is greater than LOG_MAX_SIZE, the size returned by vsnprintf will also be greater than LOG_MAX_SIZE. Therefore, the subsequent snprintf will cause a memory overflow and corrupt the stack. It is recommended to place the content to be written by snprintf before vsnprintf.

TRANS_BY_GPT3

@dean-river dean-river changed the title srs_error 级别的日志长度大于4096时会内存越界,破坏堆栈导致崩溃 srs_error 级别的日志内容长度大于4096时会内存越界,破坏堆栈导致崩溃 Sep 24, 2018
@winlinvip winlinvip added the Bug It might be a bug. label Oct 7, 2018
@winlinvip winlinvip added this to the srs 2.0 release milestone Oct 7, 2018
@winlinvip
Copy link
Member

winlinvip commented Oct 7, 2018

Can you help submit a Pull Request? Please make sure to maintain the markdown structure.

TRANS_BY_GPT3

@winlinvip
Copy link
Member

winlinvip commented Dec 11, 2019

I checked the manual:

     int printf(const char * restrict format, ...);
     int sprintf(char * restrict str, const char * restrict format, ...);
     int snprintf(char * restrict str, size_t size, const char * restrict format, ...);
     int vsnprintf(char * restrict str, size_t size, const char * restrict format, va_list ap);

RETURN VALUES
     These functions return the number of characters printed (not including the trailing `\0' used to end output to strings), except for
     snprintf() and vsnprintf(), which return the number of characters that would have been printed if the size were unlimited (again, not
     including the final `\0').  These functions return a negative value if an error occurs.

The single test program is as follows:

#define _ARRAY_INIT(buf, sz, val) \
    for (int i = 0; i < (int)sz; i++) buf[i]=val

VOID TEST(CoreLogger, CheckVsnprintf)
{
    if (true) {
        char buf[1024];
        _ARRAY_INIT(buf, sizeof(buf), 0xf);

        // Return the number of characters printed.
        EXPECT_EQ(6, sprintf(buf, "%s", "Hello!"));
        EXPECT_EQ('H', buf[0]);
        EXPECT_EQ('!', buf[5]);
        EXPECT_EQ(0x0, buf[6]);
        EXPECT_EQ(0xf, buf[7]);
    }

    if (true) {
        char buf[1024];
        _ARRAY_INIT(buf, sizeof(buf), 0xf);

        // Return the number of characters that would have been printed if the size were unlimited.
        EXPECT_EQ(6, snprintf(buf, 3, "%s", "Hello!"));
        EXPECT_EQ('H', buf[0]);
        EXPECT_EQ('e', buf[1]);
        EXPECT_EQ(0, buf[2]);
        EXPECT_EQ(0xf, buf[3]);
    }
}

This risk has been resolved at 78da67e.

There may be security risks with sprintf and vsprintf due to the lack of string length restrictions.

SECURITY CONSIDERATIONS
     The sprintf() and vsprintf() functions are easily misused in a manner which enables malicious users to arbitrarily change a running pro-
     gram's functionality through a buffer overflow attack.  Because sprintf() and vsprintf() assume an infinitely long string, callers must
     be careful not to overflow the actual space; this is often hard to assure.  For safety, programmers should use the snprintf() interface
     instead.

SRS is mainly used in HDS and has been fixed at ad70589. It is also used in JSON and appears to have no risks.

Thank you @dean-river 👍

TRANS_BY_GPT3

@winlinvip winlinvip self-assigned this Sep 11, 2021
@winlinvip winlinvip changed the title srs_error 级别的日志内容长度大于4096时会内存越界,破坏堆栈导致崩溃 When the length of the log content of the 'srs_error' level exceeds 4096, it will cause a memory overflow, leading to a stack corruption and a crash. Jul 28, 2023
@winlinvip winlinvip added the TransByAI Translated by AI/GPT. label Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug It might be a bug. TransByAI Translated by AI/GPT.
Projects
None yet
Development

No branches or pull requests

2 participants