diff options
author | Venkatesh Duggirala <venkatesh.duggirala@oracle.com> | 2015-12-01 15:38:11 +0530 |
---|---|---|
committer | Venkatesh Duggirala <venkatesh.duggirala@oracle.com> | 2015-12-01 15:38:11 +0530 |
commit | 2735f0b92020c8ac4bd07d7ea843a0946b19e8ad (patch) | |
tree | f698248dc83ac973eec6eb91e6b3994b019b3fea /sql/log_event.cc | |
parent | 08e929388b2cea170f6a44e9c8669f9c0f636808 (diff) | |
download | mariadb-git-2735f0b92020c8ac4bd07d7ea843a0946b19e8ad.tar.gz |
Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK
Problem:
========
1) Drop table queries are re-generated by server
before writing the events(queries) into binlog
for various reasons. If table name/db name contains
a non regular characters (like latin characters),
the generated query is wrong. Hence it breaks the
replication.
2) In the edge case, when table name/db name contains
64 characters, server is throwing an assert
assert(M_TBLLEN < 128)
3) In the edge case, when db name contains 64 latin
characters, binlog content is interpreted badly
which is leading replication failure.
Analysis & Fix :
================
1) Parser reads the table name from the query and converts
it to standard charset(utf8) and stores it in table_name variable.
When drop table query is regenerated with the same table_name
variable, it should be converted back to the original charset
from standard charset(utf8).
2) Latin character takes two bytes for each character. Limit
of the identifier is 64. SYSTEM_CHARSET_MBMAXLEN is set to '3'.
So there is a possiblity that tablename/dbname contains 3 * 64.
Hence assert is changed to
(M_TBLLEN <= NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN)
3) db_len in the binlog event header is taking 1 byte.
db_len is ranged from 0 to 192 bytes (3 * 64).
While reading the db_len from the event, server
is casting to uint instead of uchar which is leading
to bad db_len. This problem is fixed by changing the
cast type to uchar.
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 38efb2a9c6b..accb6a28dbd 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2792,7 +2792,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars + db_len = (uchar)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -8960,9 +8960,9 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) { DBUG_ASSERT(m_dbnam != NULL); DBUG_ASSERT(m_tblnam != NULL); - /* We use only one byte per length for storage in event: */ - DBUG_ASSERT(m_dblen < 128); - DBUG_ASSERT(m_tbllen < 128); + + DBUG_ASSERT(m_dblen <= NAME_LEN); + DBUG_ASSERT(m_tbllen <= NAME_LEN); uchar const dbuf[]= { (uchar) m_dblen }; uchar const tbuf[]= { (uchar) m_tbllen }; |