diff options
author | Andrei Elkin <aelkin@mysql.com> | 2009-03-25 12:53:56 +0200 |
---|---|---|
committer | Andrei Elkin <aelkin@mysql.com> | 2009-03-25 12:53:56 +0200 |
commit | 67f9a6d1782ff9f00769816fdf3dfb1e9763bba7 (patch) | |
tree | d96b69ccd9147ab28ede5b29b49d423d7e1d29ea /sql/log_event.cc | |
parent | 6c0abff9284511914e14ae9339f858101feca99a (diff) | |
download | mariadb-git-67f9a6d1782ff9f00769816fdf3dfb1e9763bba7.tar.gz |
Bug#42977 RBR logs for rows with more than 250 column results in corrupt binlog
The issue happened to be two-fold.
The table map event was recorded into binlog having
an incorrect size when number of columns exceeded 251.
The Row-based event had incorrect recording and restoring m_width member within
the same as above conditions.
Fixed with correcting m_data_size and m_width.
mysql-test/suite/rpl/r/rpl_row_wide_table.result:
the new test results.
mysql-test/suite/rpl/t/rpl_row_wide_table.test:
regression test for bug#42977.
sql/log_event.cc:
0. all buffers that used in net_store_length() are augmented with 1 for safety
to be able to contain the magic and the content of ulonglong as well;
1. Rows_log_event::get_data_size() yieled incorrect size |m_width/8| whereas
it should be m_width;
2. Table_map_log_event::Table_map_log_event yieled incorrect value for
`m_data_size' probably presuming 1-byte integer max for the column number;
sql/rpl_utility.h:
DBUG_PRINT_BITSET() macro is left 256-cols limited but has made safe and commented.
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index aa7e8c84a0f..6220bc276a6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6993,8 +6993,8 @@ int Rows_log_event::get_data_size() { int const type_code= get_type_code(); - uchar buf[sizeof(m_width)+1]; - uchar *end= net_store_length(buf, (m_width + 7) / 8); + uchar buf[sizeof(m_width) + 1]; + uchar *end= net_store_length(buf, m_width); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", return 6 + no_bytes_in_map(&m_cols) + (end - buf) + @@ -7583,7 +7583,7 @@ bool Rows_log_event::write_data_body(IO_CACHE*file) Note that this should be the number of *bits*, not the number of bytes. */ - uchar sbuf[sizeof(m_width)]; + uchar sbuf[sizeof(m_width) + 1]; my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; bool res= false; uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width); @@ -7745,6 +7745,8 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_null_bits(0), m_meta_memory(NULL) { + uchar cbuf[sizeof(m_colcnt) + 1]; + uchar *cbuf_end; DBUG_ASSERT(m_table_id != ~0UL); /* In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in @@ -7761,7 +7763,9 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;); m_data_size+= m_dblen + 2; // Include length and terminating \0 m_data_size+= m_tbllen + 2; // Include length and terminating \0 - m_data_size+= 1 + m_colcnt; // COLCNT and column types + cbuf_end= net_store_length(cbuf, (size_t) m_colcnt); + DBUG_ASSERT((cbuf_end - cbuf) <= sizeof(cbuf)); + m_data_size+= (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types /* If malloc fails, caught in is_valid() */ if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME)))) @@ -8053,7 +8057,7 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) uchar const dbuf[]= { (uchar) m_dblen }; uchar const tbuf[]= { (uchar) m_tbllen }; - uchar cbuf[sizeof(m_colcnt)]; + uchar cbuf[sizeof(m_colcnt) + 1]; uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt); DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf)); |