Skip to content

Commit

Permalink
MDEV-11319 mysqlbinlog crashes or fails with out of memory while read…
Browse files Browse the repository at this point in the history
…ing some encrypted binlogs

support encrypted binlogs. Not decryption, but at least recognizing
that event are encrypted and prining them as such
  • Loading branch information
vuvova committed Dec 6, 2016
1 parent 952856c commit b5aa0f4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 5 deletions.
12 changes: 11 additions & 1 deletion client/mysqlbinlog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto err;
break;
}
case START_ENCRYPTION_EVENT:
glob_description_event->start_decryption((Start_encryption_log_event*)ev);
/* fall through */
default:
print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
Expand Down Expand Up @@ -2837,9 +2840,16 @@ void *sql_alloc(size_t size)
return alloc_root(&s_mem_root, size);
}

uint dummy1() { return 1; }
struct encryption_service_st encryption_handler=
{
0, 0, 0, 0, 0, 0, 0
(uint(*)(uint))dummy1,
(uint(*)(uint, uint, uchar*, uint*))dummy1,
(uint(*)(uint, uint))dummy1,
(int (*)(void*, const uchar*, uint, const uchar*, uint, int, uint, uint))dummy1,
(int (*)(void*, const uchar*, uint, uchar*, uint*))dummy1,
(int (*)(void*, uchar*, uint*))dummy1,
(uint (*)(uint, uint, uint))dummy1
};

/*
Expand Down
6 changes: 6 additions & 0 deletions mysql-test/suite/binlog_encryption/mysqlbinlog.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
RESET MASTER;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
REPLACE INTO t1 VALUES (4);
DROP TABLE t1;
FLUSH LOGS;
21 changes: 21 additions & 0 deletions mysql-test/suite/binlog_encryption/mysqlbinlog.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
source include/have_log_bin.inc;
source include/have_debug.inc;

let datadir=`select @@datadir`;
RESET MASTER;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
REPLACE INTO t1 VALUES (4);
DROP TABLE t1;
FLUSH LOGS;

let filename= master-bin.000001;
let local=$datadir/$filename;
let remote=--read-from-remote-server --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT -uroot $filename;
let outfile=$MYSQLTEST_VARDIR/tmp/binlog_enc.sql;
--error 1
exec $MYSQL_BINLOG $local > $outfile;
exec $MYSQL_BINLOG $local --force-read >> $outfile;
exec $MYSQL_BINLOG $remote >> $outfile;
remove_file $outfile;

13 changes: 11 additions & 2 deletions sql/log_event.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,10 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, mysql_mutex_t* log_lock,
if (error)
{
DBUG_ASSERT(!res);
#ifdef MYSQL_CLIENT
if (force_opt)
DBUG_RETURN(new Unknown_log_event());
#endif
if (event.length() >= OLD_HEADER_LEN)
sql_print_error("Error in Log_event::read_log_event(): '%s',"
" data_len: %lu, event_type: %d", error,
Expand Down Expand Up @@ -8182,8 +8186,13 @@ void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info

if (print_event_info->short_form)
return;
print_header(&cache, print_event_info, FALSE);
my_b_printf(&cache, "\n# %s", "Unknown event\n");
if (what != ENCRYPTED)
{
print_header(&cache, print_event_info, FALSE);
my_b_printf(&cache, "\n# Unknown event\n");
}
else
my_b_printf(&cache, "# Encrypted event\n");
}
#endif

Expand Down
7 changes: 5 additions & 2 deletions sql/log_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ class Log_event
return thd ? thd->db : 0;
}
#else
Log_event() : temp_buf(0), flags(0) {}
Log_event() : temp_buf(0), when(0), flags(0) {}
ha_checksum crc;
/* print*() functions are used by mysqlbinlog */
virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0;
Expand Down Expand Up @@ -3677,15 +3677,18 @@ class Execute_load_query_log_event: public Query_log_event
class Unknown_log_event: public Log_event
{
public:
enum { UNKNOWN, ENCRYPTED } what;
/*
Even if this is an unknown event, we still pass description_event to
Log_event's ctor, this way we can extract maximum information from the
event's header (the unique ID for example).
*/
Unknown_log_event(const char* buf,
const Format_description_log_event *description_event):
Log_event(buf, description_event)
Log_event(buf, description_event), what(UNKNOWN)
{}
/* constructor for hopelessly corrupted events */
Unknown_log_event(): Log_event(), what(ENCRYPTED) {}
~Unknown_log_event() {}
void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
Log_event_type get_type_code() { return UNKNOWN_EVENT;}
Expand Down

0 comments on commit b5aa0f4

Please sign in to comment.