diff --git a/sql/log_event.cc b/sql/log_event.cc index 4a421e33893..a97a95a116c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5145,9 +5145,31 @@ int Format_description_log_event::pack_info(Protocol *protocol) { bool Format_description_log_event::write(Basic_ostream *ostream) { bool ret; bool no_checksum; - uchar buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN + - BINLOG_CHECKSUM_ALG_DESC_LEN]; - size_t rec_size = sizeof(buff); + + /* + Going with stack allocated buffer to handle format description events. + Since the actual size of the format description event depends on the mysql + version, the buffer size needs to be adjusted based on the length of the + format_description_event from the post_header_len. Since the length is + stored in a single byte, it should never be greater than 255 bytes. + */ + const size_t MAX_FD_LEN = 256; + DBUG_ASSERT(MAX_FD_LEN > binary_log::FORMAT_DESCRIPTION_EVENT); + int num_log_event_types = + post_header_len[binary_log::FORMAT_DESCRIPTION_EVENT - 1] - + Binary_log_event::START_V3_HEADER_LEN - 1; + + /* Smaller length than expected, revert to original behavior */ + DBUG_ASSERT(num_log_event_types >= binary_log::FORMAT_DESCRIPTION_EVENT); + if (num_log_event_types < binary_log::FORMAT_DESCRIPTION_EVENT) + num_log_event_types = Binary_log_event::LOG_EVENT_TYPES; + + uchar buff[MAX_FD_LEN + BINLOG_CHECKSUM_ALG_DESC_LEN]; + size_t format_description_header_len = + Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN - LOG_EVENT_TYPES + + num_log_event_types; + size_t rec_size = + format_description_header_len + BINLOG_CHECKSUM_ALG_DESC_LEN; int2store(buff + ST_BINLOG_VER_OFFSET, binlog_version); memcpy((char *)buff + ST_SERVER_VER_OFFSET, server_version, ST_SERVER_VER_LEN); @@ -5155,7 +5177,7 @@ bool Format_description_log_event::write(Basic_ostream *ostream) { int4store(buff + ST_CREATED_OFFSET, static_cast(created)); buff[ST_COMMON_HEADER_LEN_OFFSET] = LOG_EVENT_HEADER_LEN; memcpy((char *)buff + ST_COMMON_HEADER_LEN_OFFSET + 1, &post_header_len[0], - Binary_log_event::LOG_EVENT_TYPES); + num_log_event_types); /* if checksum is requested record the checksum-algorithm descriptor next to @@ -5168,7 +5190,7 @@ bool Format_description_log_event::write(Basic_ostream *ostream) { #ifndef DBUG_OFF common_header->data_written = 0; // to prepare for need_checksum assert #endif - buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN] = + buff[format_description_header_len] = need_checksum() ? (uint8)common_footer->checksum_alg : (uint8)binary_log::BINLOG_CHECKSUM_ALG_OFF; /*