List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:February 22 2008 2:26pm
Subject:bk commit into 5.1 tree (mats:1.2652) BUG#31502
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mats. When mats does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-22 15:25:56+01:00, mats@stripped +8 -0
  BUG#31502 (5.1.20 -> 5.1.22 Slave crashes if it gets an event w/ data 
             for non-exist column):
  
  Complimentary patch to fix the fact that type() instead of real_type()
  was sent in the table map event. This cause a crash when using ENUM
  extra columns since type() is MYSQL_TYPE_STRING and real_type() is
  MYSQL_TYPE_ENUM. The packed format for MYSQL_TYPE_STRING is (len,
  byte, ...) while the pack format for MYSQL_TYPE_ENUM is just the
  integer value as a single byte (which will then be interpreted as the
  length of a string by the slave).

  sql/field.cc@stripped, 2008-02-22 15:25:43+01:00, mats@stripped +8 -11
    Removing debug printouts that are not needed any more.
    In Field_string::unpack(), only 'min(field_length,length)' bytes
    were read from the log, although 'length' bytes should be read,
    since this is what is stored in the log. Changing the code so
    that the function advances the point 'length' bytes, but just
    copy 'min(field_length,lenght)' bytes from the buffer. This way
    there is no risk of buffer overflow when length > field_length.

  sql/field.h@stripped, 2008-02-22 15:25:44+01:00, mats@stripped +8 -2
    Removing gratuitous virtual for save_field_metadata(): the function
    is never overridden. Adding debug printout to save_field_metadata().
    

  sql/log_event.cc@stripped, 2008-02-22 15:25:45+01:00, mats@stripped +1 -1
    Storing real_type() instead of type() in the coltype array.

  sql/log_event.h@stripped, 2008-02-22 15:25:45+01:00, mats@stripped +2 -1
    Removing gratuitous virtual on save_field_metadata(): the
    function is never overridden. Adding end of all rows to
    unpack_row() to allow for checking if reading out of bounds.

  sql/log_event_old.h@stripped, 2008-02-22 15:25:45+01:00, mats@stripped +1 -0
    Adding end of all rows to unpack_row() to allow for checking
    if reading out of bounds.

  sql/rpl_record.cc@stripped, 2008-02-22 15:25:46+01:00, mats@stripped +20 -13
    Adding end of all rows to unpack_row() to allow for checking
    if reading out of bounds. Returning error if reading out of
    bounds. Some changes to debug printout to get good information
    for debugging.

  sql/rpl_record.h@stripped, 2008-02-22 15:25:46+01:00, mats@stripped +1 -0
    Adding parameter for end of all rows to allow check for
    reading out of bounds data.

  sql/rpl_utility.cc@stripped, 2008-02-22 15:25:46+01:00, mats@stripped +22 -6
    Not printing an error for field types that require metadata
    when we have a length value, i.e., when there were metadata
    available for the field.

diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc	2007-11-21 21:09:21 +01:00
+++ b/sql/field.cc	2008-02-22 15:25:43 +01:00
@@ -4036,39 +4036,35 @@ uchar *
 Field_real::pack(uchar *to, const uchar *from,
                  uint max_length, bool low_byte_first)
 {
-  DBUG_ENTER("Field_real::pack");
   DBUG_ASSERT(max_length >= pack_length());
-  DBUG_PRINT("debug", ("pack_length(): %u", pack_length()));
 #ifdef WORDS_BIGENDIAN
   if (low_byte_first != table->s->db_low_byte_first)
   {
     const uchar *dptr= from + pack_length();
     while (dptr-- > from)
       *to++ = *dptr;
-    DBUG_RETURN(to);
+    return to;
   }
   else
 #endif
-    DBUG_RETURN(Field::pack(to, from, max_length, low_byte_first));
+    return Field::pack(to, from, max_length, low_byte_first);
 }
 
 const uchar *
 Field_real::unpack(uchar *to, const uchar *from,
                    uint param_data, bool low_byte_first)
 {
-  DBUG_ENTER("Field_real::unpack");
-  DBUG_PRINT("debug", ("pack_length(): %u", pack_length()));
 #ifdef WORDS_BIGENDIAN
   if (low_byte_first != table->s->db_low_byte_first)
   {
     const uchar *dptr= from + pack_length();
     while (dptr-- > from)
       *to++ = *dptr;
-    DBUG_RETURN(from + pack_length());
+    return from + pack_length();
   }
   else
 #endif
-    DBUG_RETURN(Field::unpack(to, from, param_data, low_byte_first));
+    return Field::unpack(to, from, param_data, low_byte_first);
 }
 
 /****************************************************************************
@@ -6675,7 +6671,7 @@ Field_string::unpack(uchar *to,
                      bool low_byte_first __attribute__((unused)))
 {
   uint from_length=
-    param_data ? min(param_data & 0x00ff, field_length) : field_length;
+    param_data ? (param_data & 0x00ff) : field_length;
   uint length;
 
   if (from_length > 255)
@@ -6686,9 +6682,10 @@ Field_string::unpack(uchar *to,
   else
     length= (uint) *from++;
 
-  memcpy(to, from, length);
+  memcpy(to, from, min(length, field_length));
   // Pad the string with the pad character of the fields charset
-  bfill(to + length, field_length - length, field_charset->pad_char);
+  if (field_length > length)
+    bfill(to + length, field_length - length, field_charset->pad_char);
   return from+length;
 }
 
diff -Nrup a/sql/field.h b/sql/field.h
--- a/sql/field.h	2007-10-30 08:19:22 +01:00
+++ b/sql/field.h	2008-02-22 15:25:44 +01:00
@@ -167,8 +167,14 @@ public:
     field_length + 1, field_length, and pack_length_no_ptr() respectfully.
   */
   virtual uint row_pack_length() { return 0; }
-  virtual int save_field_metadata(uchar *first_byte)
-  { return do_save_field_metadata(first_byte); }
+  int save_field_metadata(uchar *first_byte)
+  {
+    int result= do_save_field_metadata(first_byte);
+    DBUG_PRINT("info", ("field: %s; type: %3d; count: %2d, data: %02x %02x",
+                        field_name, real_type(), result,
+                        first_byte[0], first_byte[1]));
+    return result;
+  }
 
   /*
     data_length() return the "real size" of the data in memory.
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-12-13 21:27:23 +01:00
+++ b/sql/log_event.cc	2008-02-22 15:25:45 +01:00
@@ -6852,7 +6852,7 @@ Table_map_log_event::Table_map_log_event
   {
     m_coltype= reinterpret_cast<uchar*>(m_memory);
     for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
-      m_coltype[i]= m_table->field[i]->type();
+      m_coltype[i]= m_table->field[i]->real_type();
   }
 
   /*
diff -Nrup a/sql/log_event.h b/sql/log_event.h
--- a/sql/log_event.h	2007-12-13 21:27:23 +01:00
+++ b/sql/log_event.h	2008-02-22 15:25:45 +01:00
@@ -2874,7 +2874,7 @@ public:
 
   virtual int get_data_size() { return m_data_size; } 
 #ifndef MYSQL_CLIENT
-  virtual int save_field_metadata();
+  int save_field_metadata();
   virtual bool write_data_header(IO_CACHE *file);
   virtual bool write_data_body(IO_CACHE *file);
   virtual const char *get_db() { return m_dbnam; }
@@ -3097,6 +3097,7 @@ 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_rows_end,
                                    &m_curr_row_end, &m_master_reclength);
     ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
     return result;
diff -Nrup a/sql/log_event_old.h b/sql/log_event_old.h
--- a/sql/log_event_old.h	2007-11-20 19:49:34 +01:00
+++ b/sql/log_event_old.h	2008-02-22 15:25:45 +01:00
@@ -212,6 +212,7 @@ 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_rows_end,
                                    &m_curr_row_end, &m_master_reclength);
     ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
     return result;
diff -Nrup a/sql/rpl_record.cc b/sql/rpl_record.cc
--- a/sql/rpl_record.cc	2007-12-13 21:27:24 +01:00
+++ b/sql/rpl_record.cc	2008-02-22 15:25:46 +01:00
@@ -77,8 +77,10 @@ pack_row(TABLE *table, MY_BITMAP const* 
   unsigned int null_mask= 1U;
   for ( ; (field= *p_field) ; p_field++)
   {
-    DBUG_PRINT("debug", ("null_mask=%d; null_ptr=%p; row_data=%p; null_byte_count=%d",
-                         null_mask, null_ptr, row_data, null_byte_count));
+    DBUG_PRINT("debug", ("field: %s; type: %d",
+                         field->field_name, field->real_type()));
+    DBUG_PRINT("debug", ("null_mask=%d; null_ptr=%p; null_byte_count=%d",
+                         null_mask, null_ptr, null_byte_count));
     if (bitmap_is_set(cols, p_field - table->field))
     {
       my_ptrdiff_t offset;
@@ -104,11 +106,10 @@ pack_row(TABLE *table, MY_BITMAP const* 
 #endif
         pack_ptr= field->pack(pack_ptr, field->ptr + offset,
                               field->max_data_length(), TRUE);
-        DBUG_PRINT("debug", ("field: %s; pack_ptr: 0x%lx;"
-                             " pack_ptr':0x%lx; bytes: %d",
-                             field->field_name, (ulong) old_pack_ptr,
-                             (ulong) pack_ptr,
+        DBUG_PRINT("debug", ("pack_ptr: 0x%lx; pack_ptr':0x%lx; bytes: %d",
+                             (ulong) old_pack_ptr, (ulong) pack_ptr,
                              (int) (pack_ptr - old_pack_ptr)));
+        DBUG_DUMP("row_data", old_pack_ptr, pack_ptr - old_pack_ptr);
       }
 
       null_mask <<= 1;
@@ -186,6 +187,7 @@ 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 data_end,
            uchar const **const row_end, ulong *const master_reclength)
 {
   DBUG_ENTER("unpack_row");
@@ -247,11 +249,12 @@ unpack_row(Relay_log_info const *rli,
         uchar const *const old_pack_ptr= pack_ptr;
 #endif
         pack_ptr= f->unpack(f->ptr, pack_ptr, metadata, TRUE);
-	DBUG_PRINT("debug", ("field: %s; type: %d; metadata: 0x%x;"
-                             " pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
-                             f->field_name, f->type(), metadata,
+	DBUG_PRINT("debug", ("field: %s; type: %d; metadata: 0x%x",
+                             f->field_name, f->type(), metadata));
+	DBUG_PRINT("debug", ("pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
                              (ulong) old_pack_ptr, (ulong) pack_ptr,
                              (int) (pack_ptr - old_pack_ptr)));
+        DBUG_DUMP("row_data", old_pack_ptr, pack_ptr - old_pack_ptr);
       }
 
       null_mask <<= 1;
@@ -262,8 +265,8 @@ unpack_row(Relay_log_info const *rli,
   /*
     throw away master's extra fields
   */
-  DBUG_PRINT("info", ("i: %u; tabledef->size: %lu; cols->n_bits: %u",
-                      i, tabledef->size(), cols->n_bits));
+  DBUG_PRINT("info", ("tabledef->size: %lu; cols->n_bits: %u",
+                      tabledef->size(), cols->n_bits));
   uint max_cols= min(tabledef->size(), cols->n_bits);
   for (; i < max_cols; i++)
   {
@@ -282,9 +285,13 @@ unpack_row(Relay_log_info const *rli,
         if ((error= tabledef->calc_field_size(i, (uchar *) pack_ptr, &length, rli)))
           DBUG_RETURN(error);
         DBUG_PRINT("info",
-                   ("type: %d; pack_ptr: 0x%lu; pack_ptr': 0x%lu",
-                    tabledef->type(i),
+                   ("type: %d; metadata: 0x%04x; bytes: %d",
+                    tabledef->type(i), tabledef->field_metadata(i), length));
+        DBUG_PRINT("info",
+                   ("pack_ptr: 0x%lu; pack_ptr': 0x%lu",
                     (ulong) pack_ptr, (ulong) pack_ptr + length));
+        DBUG_DUMP("row_data", pack_ptr, min(length, 128));
+        ASSERT_OR_RETURN_ERROR(pack_ptr + length <= data_end, HA_ERR_CORRUPT_EVENT);
         pack_ptr += length;
       }
       null_mask <<= 1;
diff -Nrup a/sql/rpl_record.h b/sql/rpl_record.h
--- a/sql/rpl_record.h	2007-09-10 13:15:59 +02:00
+++ b/sql/rpl_record.h	2008-02-22 15:25:46 +01:00
@@ -27,6 +27,7 @@ size_t pack_row(TABLE* table, MY_BITMAP 
 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 data_end,
                uchar const **const row_end, ulong *const master_reclength);
 
 // Fill table's record[0] with default values.
diff -Nrup a/sql/rpl_utility.cc b/sql/rpl_utility.cc
--- a/sql/rpl_utility.cc	2007-12-13 21:27:24 +01:00
+++ b/sql/rpl_utility.cc	2008-02-22 15:25:46 +01:00
@@ -77,9 +77,14 @@ check_and_set_length(enum_field_types fi
   case MYSQL_TYPE_VARCHAR:
   case MYSQL_TYPE_BIT:
   case MYSQL_TYPE_DECIMAL:                      // ???
-    log->report(ERROR_LEVEL, ER_SLAVE_MISSING_METADATA,
-                ER(ER_SLAVE_MISSING_METDATA), field_type);
-    error= HA_ERR_SLAVE_MISSING_METADATA;
+    if (length)
+      *out_length = length;
+    else
+    {
+      log->report(ERROR_LEVEL, ER_SLAVE_MISSING_METADATA,
+                ER(ER_SLAVE_MISSING_METADATA), field_type);
+      error= HA_ERR_SLAVE_MISSING_METADATA;
+    }
     break;
   }
   return error;
@@ -192,7 +197,7 @@ table_def::calc_field_size(uint col, uch
   case MYSQL_TYPE_BLOB:
   case MYSQL_TYPE_GEOMETRY:
   {
-#if 1
+#if 0
     /*
       BUG#29549: 
       This is currently broken for NDB, which is using big-endian
@@ -232,7 +237,7 @@ table_def::calc_field_size(uint col, uch
     break;
   }
   default:
-    length= -1;
+    length= 0;
   }
 
   int const error= check_and_set_length(type(col), length, log, len_arg);
@@ -258,7 +263,18 @@ table_def::compatible_with(Relay_log_inf
 
   for (uint col= 0 ; col < cols_to_check ; ++col)
   {
-    if (table->field[col]->type() != type(col))
+    /*
+      Here we check if the type we received is different from the real
+      type of the column. If it is, there is a problem and an error is
+      reported.
+
+      To be able to replication from old servers not having metadata,
+      we check the type (instead of the real type) since this is what
+      was stored instead of the real type.
+     */
+    if (table->field[col]->real_type() != type(col) ||
+        (m_field_metadata[col] == 0 &&
+           table->field[col]->real_type() != type(col)))
     {
       DBUG_ASSERT(col < size() && col < tsh->fields);
       DBUG_ASSERT(tsh->db.str && tsh->table_name.str);
Thread
bk commit into 5.1 tree (mats:1.2652) BUG#31502Mats Kindahl22 Feb
  • Re: bk commit into 5.1 tree (mats:1.2652) BUG#31502Andrei Elkin27 Feb