1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug#17632978 SLAVE CRASHES IF ROW EVENT IS CORRUPTED

(MYSQLBINLOG -V CRASHES WITH THAT BINLOG)

Problem: If slave receives a corrupted row event,
slave server is crashing.

Analysis: When slave is unpacking the row event, it is
not validating the data before applying the event. If the
data is corrupted for eg: the length of a field is wrong,
it could end up reading wrong data leading to a crash.
A similar problem happens when mysqlbinlog tool is used
against a corrupted binlog using '-v' option. Due to -v
option, the tool tries to print the values of all the
fields. Corrupted field length could lead to a crash.

Fix: Before unpacking the field, a verification
will be made on the length. If it falls into the event
range, only then it will be unpacked. Otherwise,
"ER_SLAVE_CORRUPT_EVENT" error will be thrown.
Incase mysqlbinlog -v case, the field value will not be
printed and the processing of the file will be stopped.

sql/field.h:
  Removed a function which is not required anymore
sql/log_event.cc:
  Adding a validation on the field length before
  the tool tries to print the value.
sql/log_event.h:
  Changing unpack_row call according to the new arguments
sql/log_event_old.h:
  Changing unpack_row call according to the new arguments
sql/rpl_record.cc:
  Adding a new argument 'row_end' which tells
  the end position of the complete data in the
  row event. It will be used to do validation
  before doing 'unpack' field.
sql/rpl_record.h:
  Adding a new argument 'row_end' which tells
  the end position of the complete data in the
  row event. It will be used to do validation
  before doing 'unpack' field.
sql/rpl_utility.cc:
  Now calc_field_size() is required for client too.
This commit is contained in:
Venkatesh Duggirala
2013-12-17 22:11:22 +05:30
parent afd24eb63d
commit 5fa9664b07
7 changed files with 41 additions and 45 deletions

View File

@ -186,7 +186,7 @@ int compare_lengths(Field *field, enum_field_types source_type, uint16 metadata)
DBUG_PRINT("result", ("%d", result));
DBUG_RETURN(result);
}
#endif //MYSQL_CLIENT
/*********************************************************************
* table_def member definitions *
*********************************************************************/
@ -285,7 +285,6 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
case MYSQL_TYPE_VARCHAR:
{
length= m_field_metadata[col] > 255 ? 2 : 1; // c&p of Field_varstring::data_length()
DBUG_ASSERT(uint2korr(master_data) > 0);
length+= length == 1 ? (uint32) *master_data : uint2korr(master_data);
break;
}
@ -295,17 +294,6 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
{
#if 1
/*
BUG#29549:
This is currently broken for NDB, which is using big-endian
order when packing length of BLOB. Once they have decided how to
fix the issue, we can enable the code below to make sure to
always read the length in little-endian order.
*/
Field_blob fb(m_field_metadata[col]);
length= fb.get_packed_size(master_data, TRUE);
#else
/*
Compute the length of the data. We cannot use get_length() here
since it is dependent on the specific table (and also checks the
@ -331,7 +319,6 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
}
length+= m_field_metadata[col];
#endif
break;
}
default:
@ -340,7 +327,7 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
return length;
}
#ifndef MYSQL_CLIENT
/**
*/
void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_INFO *field_cs)