summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/field.h14
-rw-r--r--sql/log_event.cc9
-rw-r--r--sql/log_event.h8
-rw-r--r--sql/log_event_old.h6
-rw-r--r--sql/rpl_record.cc27
-rw-r--r--sql/rpl_record.h5
-rw-r--r--sql/rpl_utility.cc17
7 files changed, 41 insertions, 45 deletions
diff --git a/sql/field.h b/sql/field.h
index d9f0b892adb..6a181b7ae91 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1,7 +1,7 @@
#ifndef FIELD_INCLUDED
#define FIELD_INCLUDED
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2013, 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
@@ -1802,18 +1802,6 @@ public:
{
store_length(ptr, packlength, number);
}
-
- /**
- Return the packed length plus the length of the data.
-
- This is used to determine the size of the data plus the
- packed length portion in the row data.
-
- @returns The length in the row plus the size of the data.
- */
- uint32 get_packed_size(const uchar *ptr_arg, bool low_byte_first)
- {return packlength + get_length(ptr_arg, packlength, low_byte_first);}
-
inline uint32 get_length(uint row_offset= 0)
{ return get_length(ptr+row_offset, this->packlength, table->s->db_low_byte_first); }
uint32 get_length(const uchar *ptr, uint packlength, bool low_byte_first);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 7d18b447084..122953b48ec 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -18,6 +18,7 @@
#ifdef MYSQL_CLIENT
#include "sql_priv.h"
+#include "mysqld_error.h"
#else
@@ -1945,6 +1946,14 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td,
else
{
my_b_printf(file, "### @%d=", i + 1);
+ size_t fsize= td->calc_field_size((uint)i, (uchar*) value);
+ if (value + fsize > m_rows_end)
+ {
+ my_b_printf(file, "***Corrupted replication event was detected."
+ " Not printing the value***\n");
+ value+= fsize;
+ return 0;
+ }
size_t size= log_event_print_value(file, value,
td->type(i), td->field_metadata(i),
typestr, sizeof(typestr));
diff --git a/sql/log_event.h b/sql/log_event.h
index fa17b32bef2..460d7244d07 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -3732,12 +3732,8 @@ protected:
DBUG_ASSERT(m_table);
ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT);
- int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
- &m_curr_row_end, &m_master_reclength);
- if (m_curr_row_end > m_rows_end)
- my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
- ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
- return result;
+ return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
+ &m_curr_row_end, &m_master_reclength, m_rows_end);
}
#endif
diff --git a/sql/log_event_old.h b/sql/log_event_old.h
index ab8196c0979..04678ffff84 100644
--- a/sql/log_event_old.h
+++ b/sql/log_event_old.h
@@ -203,10 +203,8 @@ protected:
{
DBUG_ASSERT(m_table);
ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT);
- int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
- &m_curr_row_end, &m_master_reclength);
- ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
- return result;
+ return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
+ &m_curr_row_end, &m_master_reclength, m_rows_end);
}
#endif
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index fc123acb104..347915405d9 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2007, 2013, 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
@@ -169,11 +169,15 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
@param row_data
Packed row data
@param cols Pointer to bitset describing columns to fill in
- @param row_end Pointer to variable that will hold the value of the
- one-after-end position for the row
+ @param curr_row_end
+ Pointer to variable that will hold the value of the
+ one-after-end position for the current row
@param master_reclength
Pointer to variable that will be set to the length of the
record on the master side
+ @param row_end
+ Pointer to variable that will hold the value of the
+ end position for the data in the row event
@retval 0 No error
@@ -185,7 +189,8 @@ int
unpack_row(Relay_log_info const *rli,
TABLE *table, uint const colcnt,
uchar const *const row_data, MY_BITMAP const *cols,
- uchar const **const row_end, ulong *const master_reclength)
+ uchar const **const current_row_end, ulong *const master_reclength,
+ uchar const *const row_end)
{
DBUG_ENTER("unpack_row");
DBUG_ASSERT(row_data);
@@ -303,6 +308,13 @@ unpack_row(Relay_log_info const *rli,
#ifndef DBUG_OFF
uchar const *const old_pack_ptr= pack_ptr;
#endif
+ uint32 len= tabledef->calc_field_size(i, (uchar *) pack_ptr);
+ if ( pack_ptr + len > row_end )
+ {
+ pack_ptr+= len;
+ my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
+ DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT);
+ }
pack_ptr= f->unpack(f->ptr, pack_ptr, metadata, TRUE);
DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;"
" pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
@@ -369,6 +381,11 @@ unpack_row(Relay_log_info const *rli,
uint32 len= tabledef->calc_field_size(i, (uchar *) pack_ptr);
DBUG_DUMP("field_data", pack_ptr, len);
pack_ptr+= len;
+ if ( pack_ptr > row_end )
+ {
+ my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
+ DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT);
+ }
}
null_mask <<= 1;
}
@@ -382,7 +399,7 @@ unpack_row(Relay_log_info const *rli,
DBUG_DUMP("row_data", row_data, pack_ptr - row_data);
- *row_end = pack_ptr;
+ *current_row_end = pack_ptr;
if (master_reclength)
{
if (*field_ptr)
diff --git a/sql/rpl_record.h b/sql/rpl_record.h
index e7d80960fe4..df3e6873af2 100644
--- a/sql/rpl_record.h
+++ b/sql/rpl_record.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2007, 2013, 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
@@ -32,7 +32,8 @@ size_t pack_row(TABLE* table, MY_BITMAP const* cols,
int unpack_row(Relay_log_info const *rli,
TABLE *table, uint const colcnt,
uchar const *const row_data, MY_BITMAP const *cols,
- uchar const **const row_end, ulong *const master_reclength);
+ uchar const **const curr_row_end, ulong *const master_reclength,
+ uchar const *const row_end);
// Fill table's record[0] with default values.
int prepare_record(TABLE *const table, const uint skip, const bool check);
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index 1527676ee58..16db07af4c2 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -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)