diff --git a/mysql-test/suite/rpl/r/rpl_read_old_relay_log_info.result b/mysql-test/suite/rpl/r/rpl_read_old_relay_log_info.result index 151a00a514b24..d4f7f3d982282 100644 --- a/mysql-test/suite/rpl/r/rpl_read_old_relay_log_info.result +++ b/mysql-test/suite/rpl/r/rpl_read_old_relay_log_info.result @@ -12,4 +12,11 @@ START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc # Check that relay log coordinates are equal to those we saved in old-format_relay-log.info = , 0, slave-relay-bin.000001, 4 +# +# MDEV-38020: Master & relay log info files read 2^31 and above incorrectly +# +connection server_2; +include/stop_slave.inc +include/rpl_restart_server.inc [server_number=2 parameters: --skip-slave-start] +include/assert.inc [relay_log_pos should be 2147483648 after restart] include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test index d2206b5bef79a..db910d80c41a3 100644 --- a/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test +++ b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test @@ -44,5 +44,30 @@ if (`SELECT "$master_file" != "" OR --die log coordinates changed } +--echo # +--echo # MDEV-38020: Master & relay log info files read 2^31 and above incorrectly +--echo # + +--connection server_2 +--source include/stop_slave.inc + +# Create a relay-log.info file with a position value > 2^31 +--let $MYSQLD_DATADIR= `select @@datadir` +--remove_file $MYSQLD_DATADIR/relay-log.info +--write_file $MYSQLD_DATADIR/relay-log.info +./slave-relay-bin.000001 +2147483648 + +0 +EOF + +--let $rpl_server_number= 2 +--let $rpl_server_parameters= --skip-slave-start +--source include/rpl_restart_server.inc + +--let $assert_text= relay_log_pos should be 2147483648 after restart +--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = 2147483648 +--source include/assert.inc + --let $rpl_only_running_threads= 1 --source include/rpl_end.inc diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index b19a585f47ebf..bb77c46d57f57 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -448,7 +448,8 @@ file '%s')", fname); } mi->fd = fd; - int port, connect_retry, master_log_pos, lines; + int port, connect_retry, lines; + ulonglong master_log_pos; int ssl= 0, ssl_verify_server_cert= 0; float master_heartbeat_period= 0.0; char *first_non_digit; @@ -496,7 +497,7 @@ file '%s')", fname); else lines= 7; - if (init_intvar_from_file(&master_log_pos, &mi->file, 4) || + if (init_ulonglongvar_from_file(&master_log_pos, &mi->file, 4) || init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, 0) || init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, "test") || init_strvar_from_file(mi->password, sizeof(mi->password), diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 320937ed82900..4ed2f55e8317c 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -321,7 +321,8 @@ Failed to open the existing relay log info file '%s' (errno %d)", } } - int relay_log_pos, master_log_pos, lines; + ulonglong relay_log_pos, master_log_pos; + int lines; char *first_non_digit; /* @@ -374,12 +375,12 @@ Failed to open the existing relay log info file '%s' (errno %d)", else DBUG_PRINT("info", ("relay_log_info file is in old format.")); - if (init_intvar_from_file(&relay_log_pos, + if (init_ulonglongvar_from_file(&relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE) || init_strvar_from_file(group_master_log_name, sizeof(group_master_log_name), &info_file, "") || - init_intvar_from_file(&master_log_pos, &info_file, 0) || + init_ulonglongvar_from_file(&master_log_pos, &info_file, 0) || (lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY && init_intvar_from_file(&sql_delay, &info_file, 0))) { diff --git a/sql/slave.cc b/sql/slave.cc index 15eeae3145542..6e0b86fc968ac 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1608,6 +1608,27 @@ int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) DBUG_RETURN(1); } +int init_ulonglongvar_from_file(ulonglong* var, IO_CACHE* f, + ulonglong default_val) +{ + char buf[MY_INT64_NUM_DECIMAL_DIGITS]; + int error; + DBUG_ENTER("init_ulonglongvar_from_file"); + + + if (my_b_gets(f, buf, sizeof(buf))) + { + *var = (ulonglong) my_strtoll10(buf, (char**) 0, &error); + DBUG_RETURN(0); + } + else if (default_val) + { + *var = default_val; + DBUG_RETURN(0); + } + DBUG_RETURN(1); +} + int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val) { char buf[16]; diff --git a/sql/slave.h b/sql/slave.h index 02de9135c2a10..ce25bebf730ba 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -266,6 +266,8 @@ int apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd, struct rpl_group_info *rgi); int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); +int init_ulonglongvar_from_file(ulonglong* var, IO_CACHE* f, + ulonglong default_val); int init_floatvar_from_file(float* var, IO_CACHE* f, float default_val); int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val);