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