diff options
author | Sujatha <sujatha.sivakumar@mariadb.com> | 2020-01-08 13:44:06 +0530 |
---|---|---|
committer | Sujatha <sujatha.sivakumar@mariadb.com> | 2020-01-08 13:44:06 +0530 |
commit | b365b6e7d8499240133682827b077f230ed0bbfa (patch) | |
tree | 817cbb9d10186c71db392bd1b496a00f99fb587f /sql/log_event.cc | |
parent | eda719793acd90f6157bcb825722dab674376bf4 (diff) | |
parent | 8317f77ccc490c94f2f43d2e6d4104c87f232563 (diff) | |
download | mariadb-git-b365b6e7d8499240133682827b077f230ed0bbfa.tar.gz |
Merge branch '10.2' into 10.3
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 78111e86f20..d4bf6a2963a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1058,9 +1058,14 @@ row_log_event_uncompress(const Format_description_log_event *description_event, uint32 binlog_get_uncompress_len(const char *buf) { - DBUG_ASSERT((buf[0] & 0xe0) == 0x80); - uint32 lenlen = buf[0] & 0x07; uint32 len = 0; + uint32 lenlen = 0; + + if ((buf == NULL) || ((buf[0] & 0xe0) != 0x80)) + return len; + + lenlen = buf[0] & 0x07; + switch(lenlen) { case 1: @@ -4572,6 +4577,18 @@ code_name(int code) } #endif +#define VALIDATE_BYTES_READ(CUR_POS, START, EVENT_LEN) \ + do { \ + uchar *cur_pos= (uchar *)CUR_POS; \ + uchar *start= (uchar *)START; \ + uint len= EVENT_LEN; \ + uint bytes_read= (uint)(cur_pos - start); \ + DBUG_PRINT("info", ("Bytes read: %u event_len:%u.\n",\ + bytes_read, len)); \ + if (bytes_read >= len) \ + DBUG_VOID_RETURN; \ + } while (0) + /** Macro to check that there is enough space to read from memory. @@ -4582,7 +4599,6 @@ code_name(int code) #define CHECK_SPACE(PTR,END,CNT) \ do { \ DBUG_PRINT("info", ("Read %s", code_name(pos[-1]))); \ - DBUG_ASSERT((PTR) + (CNT) <= (END)); \ if ((PTR) + (CNT) > (END)) { \ DBUG_PRINT("info", ("query= 0")); \ query= 0; \ @@ -4893,7 +4909,9 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, uint32 max_length= uint32(event_len - ((const char*)(end + db_len + 1) - (buf - common_header_len))); - if (q_len != max_length) + if (q_len != max_length || + (event_len < uint((const char*)(end + db_len + 1) - + (buf - common_header_len)))) { q_len= 0; query= NULL; @@ -7073,6 +7091,8 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, { DBUG_ENTER("Load_log_event::copy_log_event"); uint data_len; + if ((int) event_len < body_offset) + DBUG_RETURN(1); char* buf_end = (char*)buf + event_len; /* this is the beginning of the post-header */ const char* data_head = buf + description_event->common_header_len; @@ -7082,9 +7102,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, table_name_len = (uint)data_head[L_TBL_LEN_OFFSET]; db_len = (uint)data_head[L_DB_LEN_OFFSET]; num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET); - - if ((int) event_len < body_offset) - DBUG_RETURN(1); + /* Sql_ex.init() on success returns the pointer to the first byte after the sql_ex structure, which is the start of field lengths array. @@ -7093,7 +7111,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, buf_end, (uchar)buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) DBUG_RETURN(1); - + data_len = event_len - body_offset; if (num_fields > data_len) // simple sanity check against corruption DBUG_RETURN(1); @@ -7657,7 +7675,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1]; uint ident_offset; - if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN) + if (event_len < (uint)(LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len)) DBUG_VOID_RETURN; buf+= LOG_EVENT_MINIMAL_HEADER_LEN; pos= post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4; @@ -9236,6 +9254,11 @@ User_var_log_event(const char* buf, uint event_len, we keep the flags set to UNDEF_F. */ size_t bytes_read= (val + val_len) - buf_start; + if (bytes_read > event_len) + { + error= true; + goto err; + } if ((data_written - bytes_read) > 0) { flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + @@ -10859,7 +10882,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, uint8 const common_header_len= description_event->common_header_len; Log_event_type event_type= (Log_event_type)(uchar)buf[EVENT_TYPE_OFFSET]; m_type= event_type; - + m_cols_ai.bitmap= 0; + uint8 const post_header_len= description_event->post_header_len[event_type-1]; DBUG_PRINT("enter",("event_len: %u common_header_len: %d " @@ -10893,7 +10917,14 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, which includes length bytes */ var_header_len= uint2korr(post_start); - assert(var_header_len >= 2); + /* Check length and also avoid out of buffer read */ + if (var_header_len < 2 || + event_len < static_cast<unsigned int>(var_header_len + + (post_start - buf))) + { + m_cols.bitmap= 0; + DBUG_VOID_RETURN; + } var_header_len-= 2; /* Iterate over var-len header, extracting 'chunks' */ @@ -12558,14 +12589,12 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, m_data_size(0), m_field_metadata(0), m_field_metadata_size(0), m_null_bits(0), m_meta_memory(NULL) { - unsigned int bytes_read= 0; DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)"); uint8 common_header_len= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[TABLE_MAP_EVENT-1]; DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d", event_len, common_header_len, post_header_len)); - /* Don't print debug messages when running valgrind since they can trigger false warnings. @@ -12574,6 +12603,9 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, DBUG_DUMP("event buffer", (uchar*) buf, event_len); #endif + if (event_len < (uint)(common_header_len + post_header_len)) + DBUG_VOID_RETURN; + /* Read the post-header */ const char *post_start= buf + common_header_len; @@ -12600,15 +12632,18 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, /* Extract the length of the various parts from the buffer */ uchar const *const ptr_dblen= (uchar const*)vpart + 0; + VALIDATE_BYTES_READ(ptr_dblen, buf, event_len); m_dblen= *(uchar*) ptr_dblen; /* Length of database name + counter + terminating null */ uchar const *const ptr_tbllen= ptr_dblen + m_dblen + 2; + VALIDATE_BYTES_READ(ptr_tbllen, buf, event_len); m_tbllen= *(uchar*) ptr_tbllen; /* Length of table name + counter + terminating null */ uchar const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2; uchar *ptr_after_colcnt= (uchar*) ptr_colcnt; + VALIDATE_BYTES_READ(ptr_after_colcnt, buf, event_len); m_colcnt= net_field_length(&ptr_after_colcnt); DBUG_PRINT("info",("m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld", @@ -12631,23 +12666,27 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, memcpy(m_coltype, ptr_after_colcnt, m_colcnt); ptr_after_colcnt= ptr_after_colcnt + m_colcnt; - bytes_read= (uint) (ptr_after_colcnt - (uchar *)buf); - DBUG_PRINT("info", ("Bytes read: %d", bytes_read)); - if (bytes_read < event_len) + VALIDATE_BYTES_READ(ptr_after_colcnt, buf, event_len); + m_field_metadata_size= net_field_length(&ptr_after_colcnt); + if(m_field_metadata_size <= (m_colcnt * 2)) { - m_field_metadata_size= net_field_length(&ptr_after_colcnt); - DBUG_ASSERT(m_field_metadata_size <= (m_colcnt * 2)); uint num_null_bytes= (m_colcnt + 7) / 8; m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME), - &m_null_bits, num_null_bytes, - &m_field_metadata, m_field_metadata_size, - NULL); + &m_null_bits, num_null_bytes, + &m_field_metadata, m_field_metadata_size, + NULL); memcpy(m_field_metadata, ptr_after_colcnt, m_field_metadata_size); ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size; memcpy(m_null_bits, ptr_after_colcnt, num_null_bytes); } + else + { + m_coltype= NULL; + my_free(m_memory); + m_memory= NULL; + DBUG_VOID_RETURN; + } } - DBUG_VOID_RETURN; } #endif @@ -14502,9 +14541,12 @@ void Update_rows_log_event::init(MY_BITMAP const *cols) Update_rows_log_event::~Update_rows_log_event() { - if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened - m_cols_ai.bitmap= 0; // so no my_free in my_bitmap_free - my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init(). + if (m_cols_ai.bitmap) + { + if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened + m_cols_ai.bitmap= 0; // so no my_free in my_bitmap_free + my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init(). + } } |