Commit 4924c619 authored by unknown's avatar unknown

BUG#24490 (segfault inside unpack_row at Field_bit_as_char::set_default()):

Field_bit::set_default() did not check the bit_len, hence used the undefined
bit_ptr, causing a crash. The patch adds a check that bit_len > 0 before
following the bit_ptr.


mysql-test/extra/rpl_tests/rpl_row_tabledefs.test:
  Doing select using ORDER BY to prevent table-internal order from
  affecting the result.
mysql-test/r/rpl_row_tabledefs_2myisam.result:
  Result change
mysql-test/r/rpl_row_tabledefs_3innodb.result:
  Result change
sql/field.cc:
  Checking bit_len before following the bit_ptr, since bit_ptr has no
  sensible value in the case that bit_len == 0.
sql/field.h:
  Field_bit::set_default() used the bit_ptr, but it is undefined,
  hence causing a crash.  In reality, the hierarchy order is not correct
  so added a TODO comment about refactoring.
sql/log_event.cc:
  Code was manipulating bits for a FIELD_TYPE_BIT field without checking
  if the bit_len was > 0, hence using an undefined bit_ptr when the
  class was actually a Field_bit_as_char.
mysql-test/t/rpl_row_tabledefs_3innodb-slave.opt:
  New BitKeeper file ``mysql-test/t/rpl_row_tabledefs_3innodb-slave.opt''
parent 2138534c
...@@ -80,28 +80,28 @@ INSERT INTO t1_bit VALUES (1,2); ...@@ -80,28 +80,28 @@ INSERT INTO t1_bit VALUES (1,2);
INSERT INTO t1_bit VALUES (2,5); INSERT INTO t1_bit VALUES (2,5);
INSERT INTO t1_char VALUES (1,2); INSERT INTO t1_char VALUES (1,2);
INSERT INTO t1_char VALUES (2,5); INSERT INTO t1_char VALUES (2,5);
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
--echo **** On Slave **** --echo **** On Slave ****
sync_slave_with_master; sync_slave_with_master;
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
SELECT a,b,x FROM t1_char; SELECT a,b,x FROM t1_char ORDER BY a;
--echo **** On Master **** --echo **** On Master ****
connection master; connection master;
UPDATE t1_int SET b=2*b WHERE a=2; UPDATE t1_int SET b=2*b WHERE a=2;
UPDATE t1_char SET b=2*b WHERE a=2; UPDATE t1_char SET b=2*b WHERE a=2;
UPDATE t1_bit SET b=2*b WHERE a=2; UPDATE t1_bit SET b=2*b WHERE a=2;
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
--echo **** On Slave **** --echo **** On Slave ****
sync_slave_with_master; sync_slave_with_master;
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
SELECT a,b,x FROM t1_char; SELECT a,b,x FROM t1_char ORDER BY a;
# Each of these inserts should generate an error and stop the slave # Each of these inserts should generate an error and stop the slave
...@@ -188,11 +188,11 @@ sync_slave_with_master; ...@@ -188,11 +188,11 @@ sync_slave_with_master;
connection master; connection master;
INSERT INTO t7 VALUES (1),(2),(3); INSERT INTO t7 VALUES (1),(2),(3);
INSERT INTO t8 VALUES (1),(2),(3); INSERT INTO t8 VALUES (1),(2),(3);
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
sync_slave_with_master; sync_slave_with_master;
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
# We will now try to update and then delete a row on the master where # We will now try to update and then delete a row on the master where
# the extra field on the slave does not have a default value. This # the extra field on the slave does not have a default value. This
...@@ -216,20 +216,20 @@ INSERT INTO t1_nodef VALUES (2,4,6); ...@@ -216,20 +216,20 @@ INSERT INTO t1_nodef VALUES (2,4,6);
--echo **** On Master **** --echo **** On Master ****
connection master; connection master;
UPDATE t1_nodef SET b=2*b WHERE a=1; UPDATE t1_nodef SET b=2*b WHERE a=1;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
--echo **** On Slave **** --echo **** On Slave ****
sync_slave_with_master; sync_slave_with_master;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
--echo **** On Master **** --echo **** On Master ****
connection master; connection master;
DELETE FROM t1_nodef WHERE a=2; DELETE FROM t1_nodef WHERE a=2;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
--echo **** On Slave **** --echo **** On Slave ****
sync_slave_with_master; sync_slave_with_master;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
--echo **** Cleanup **** --echo **** Cleanup ****
connection master; connection master;
......
...@@ -46,60 +46,60 @@ INSERT INTO t1_bit VALUES (1,2); ...@@ -46,60 +46,60 @@ INSERT INTO t1_bit VALUES (1,2);
INSERT INTO t1_bit VALUES (2,5); INSERT INTO t1_bit VALUES (2,5);
INSERT INTO t1_char VALUES (1,2); INSERT INTO t1_char VALUES (1,2);
INSERT INTO t1_char VALUES (2,5); INSERT INTO t1_char VALUES (2,5);
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
**** On Slave **** **** On Slave ****
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
a b x a b x
2 5 4711
1 2 42 1 2 42
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; 2 5 4711
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
a b HEX(x) HEX(y) HEX(z) a b HEX(x) HEX(y) HEX(z)
2 5 5 1C 1
1 2 3 15 2 1 2 3 15 2
SELECT a,b,x FROM t1_char; 2 5 5 1C 1
SELECT a,b,x FROM t1_char ORDER BY a;
a b x a b x
2 5 Foo is a bar
1 2 Just a test 1 2 Just a test
2 5 Foo is a bar
**** On Master **** **** On Master ****
UPDATE t1_int SET b=2*b WHERE a=2; UPDATE t1_int SET b=2*b WHERE a=2;
UPDATE t1_char SET b=2*b WHERE a=2; UPDATE t1_char SET b=2*b WHERE a=2;
UPDATE t1_bit SET b=2*b WHERE a=2; UPDATE t1_bit SET b=2*b WHERE a=2;
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
**** On Slave **** **** On Slave ****
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
a b x a b x
2 10 4711
1 2 42 1 2 42
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; 2 10 4711
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
a b HEX(x) HEX(y) HEX(z) a b HEX(x) HEX(y) HEX(z)
2 10 5 1C 1
1 2 3 15 2 1 2 3 15 2
SELECT a,b,x FROM t1_char; 2 10 5 1C 1
SELECT a,b,x FROM t1_char ORDER BY a;
a b x a b x
2 10 Foo is a bar
1 2 Just a test 1 2 Just a test
2 10 Foo is a bar
INSERT INTO t9 VALUES (2); INSERT INTO t9 VALUES (2);
INSERT INTO t1_nodef VALUES (1,2); INSERT INTO t1_nodef VALUES (1,2);
SHOW SLAVE STATUS; SHOW SLAVE STATUS;
...@@ -327,22 +327,22 @@ Master_SSL_Key ...@@ -327,22 +327,22 @@ Master_SSL_Key
Seconds_Behind_Master # Seconds_Behind_Master #
INSERT INTO t7 VALUES (1),(2),(3); INSERT INTO t7 VALUES (1),(2),(3);
INSERT INTO t8 VALUES (1),(2),(3); INSERT INTO t8 VALUES (1),(2),(3);
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
a a
1 1
2 2
3 3
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
a a
1 1
2 2
3 3
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
a e1 e2 e3 e4 e5 e6 e7 e8 a e1 e2 e3 e4 e5 e6 e7 e8
1 NULL NULL NULL NULL NULL NULL NULL NULL 1 NULL NULL NULL NULL NULL NULL NULL NULL
2 NULL NULL NULL NULL NULL NULL NULL NULL 2 NULL NULL NULL NULL NULL NULL NULL NULL
3 NULL NULL NULL NULL NULL NULL NULL NULL 3 NULL NULL NULL NULL NULL NULL NULL NULL
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
a e1 e2 e3 e4 e5 e6 e7 e8 a e1 e2 e3 e4 e5 e6 e7 e8
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
...@@ -358,22 +358,22 @@ INSERT INTO t1_nodef VALUES (1,2,3); ...@@ -358,22 +358,22 @@ INSERT INTO t1_nodef VALUES (1,2,3);
INSERT INTO t1_nodef VALUES (2,4,6); INSERT INTO t1_nodef VALUES (2,4,6);
**** On Master **** **** On Master ****
UPDATE t1_nodef SET b=2*b WHERE a=1; UPDATE t1_nodef SET b=2*b WHERE a=1;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b a b
1 4 1 4
2 4 2 4
**** On Slave **** **** On Slave ****
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b x a b x
1 4 3 1 4 3
2 4 6 2 4 6
**** On Master **** **** On Master ****
DELETE FROM t1_nodef WHERE a=2; DELETE FROM t1_nodef WHERE a=2;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b a b
1 4 1 4
**** On Slave **** **** On Slave ****
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b x a b x
1 4 3 1 4 3
**** Cleanup **** **** Cleanup ****
......
...@@ -46,60 +46,60 @@ INSERT INTO t1_bit VALUES (1,2); ...@@ -46,60 +46,60 @@ INSERT INTO t1_bit VALUES (1,2);
INSERT INTO t1_bit VALUES (2,5); INSERT INTO t1_bit VALUES (2,5);
INSERT INTO t1_char VALUES (1,2); INSERT INTO t1_char VALUES (1,2);
INSERT INTO t1_char VALUES (2,5); INSERT INTO t1_char VALUES (2,5);
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
a b a b
1 2 1 2
2 5 2 5
**** On Slave **** **** On Slave ****
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
a b x a b x
2 5 4711
1 2 42 1 2 42
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; 2 5 4711
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
a b HEX(x) HEX(y) HEX(z) a b HEX(x) HEX(y) HEX(z)
2 5 5 1C 1
1 2 3 15 2 1 2 3 15 2
SELECT a,b,x FROM t1_char; 2 5 5 1C 1
SELECT a,b,x FROM t1_char ORDER BY a;
a b x a b x
2 5 Foo is a bar
1 2 Just a test 1 2 Just a test
2 5 Foo is a bar
**** On Master **** **** On Master ****
UPDATE t1_int SET b=2*b WHERE a=2; UPDATE t1_int SET b=2*b WHERE a=2;
UPDATE t1_char SET b=2*b WHERE a=2; UPDATE t1_char SET b=2*b WHERE a=2;
UPDATE t1_bit SET b=2*b WHERE a=2; UPDATE t1_bit SET b=2*b WHERE a=2;
SELECT * FROM t1_int; SELECT * FROM t1_int ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
SELECT * FROM t1_bit; SELECT * FROM t1_bit ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
SELECT * FROM t1_char; SELECT * FROM t1_char ORDER BY a;
a b a b
1 2 1 2
2 10 2 10
**** On Slave **** **** On Slave ****
SELECT a,b,x FROM t1_int; SELECT a,b,x FROM t1_int ORDER BY a;
a b x a b x
2 10 4711
1 2 42 1 2 42
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; 2 10 4711
SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit ORDER BY a;
a b HEX(x) HEX(y) HEX(z) a b HEX(x) HEX(y) HEX(z)
2 10 5 1C 1
1 2 3 15 2 1 2 3 15 2
SELECT a,b,x FROM t1_char; 2 10 5 1C 1
SELECT a,b,x FROM t1_char ORDER BY a;
a b x a b x
2 10 Foo is a bar
1 2 Just a test 1 2 Just a test
2 10 Foo is a bar
INSERT INTO t9 VALUES (2); INSERT INTO t9 VALUES (2);
INSERT INTO t1_nodef VALUES (1,2); INSERT INTO t1_nodef VALUES (1,2);
SHOW SLAVE STATUS; SHOW SLAVE STATUS;
...@@ -327,22 +327,22 @@ Master_SSL_Key ...@@ -327,22 +327,22 @@ Master_SSL_Key
Seconds_Behind_Master # Seconds_Behind_Master #
INSERT INTO t7 VALUES (1),(2),(3); INSERT INTO t7 VALUES (1),(2),(3);
INSERT INTO t8 VALUES (1),(2),(3); INSERT INTO t8 VALUES (1),(2),(3);
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
a a
1 1
2 2
3 3
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
a a
1 1
2 2
3 3
SELECT * FROM t7; SELECT * FROM t7 ORDER BY a;
a e1 e2 e3 e4 e5 e6 e7 e8 a e1 e2 e3 e4 e5 e6 e7 e8
1 NULL NULL NULL NULL NULL NULL NULL NULL 1 NULL NULL NULL NULL NULL NULL NULL NULL
2 NULL NULL NULL NULL NULL NULL NULL NULL 2 NULL NULL NULL NULL NULL NULL NULL NULL
3 NULL NULL NULL NULL NULL NULL NULL NULL 3 NULL NULL NULL NULL NULL NULL NULL NULL
SELECT * FROM t8; SELECT * FROM t8 ORDER BY a;
a e1 e2 e3 e4 e5 e6 e7 e8 a e1 e2 e3 e4 e5 e6 e7 e8
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0
...@@ -358,22 +358,22 @@ INSERT INTO t1_nodef VALUES (1,2,3); ...@@ -358,22 +358,22 @@ INSERT INTO t1_nodef VALUES (1,2,3);
INSERT INTO t1_nodef VALUES (2,4,6); INSERT INTO t1_nodef VALUES (2,4,6);
**** On Master **** **** On Master ****
UPDATE t1_nodef SET b=2*b WHERE a=1; UPDATE t1_nodef SET b=2*b WHERE a=1;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b a b
1 4 1 4
2 4 2 4
**** On Slave **** **** On Slave ****
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b x a b x
1 4 3 1 4 3
2 4 6 2 4 6
**** On Master **** **** On Master ****
DELETE FROM t1_nodef WHERE a=2; DELETE FROM t1_nodef WHERE a=2;
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b a b
1 4 1 4
**** On Slave **** **** On Slave ****
SELECT * FROM t1_nodef; SELECT * FROM t1_nodef ORDER BY a;
a b x a b x
1 4 3 1 4 3
**** Cleanup **** **** Cleanup ****
......
...@@ -8455,9 +8455,12 @@ const char *Field_bit::unpack(char *to, const char *from) ...@@ -8455,9 +8455,12 @@ const char *Field_bit::unpack(char *to, const char *from)
void Field_bit::set_default() void Field_bit::set_default()
{ {
my_ptrdiff_t const offset= table->s->default_values - table->record[0]; if (bit_len > 0)
uchar bits= get_rec_bits(bit_ptr + offset, bit_ofs, bit_len); {
set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); my_ptrdiff_t const offset= table->s->default_values - table->record[0];
uchar bits= get_rec_bits(bit_ptr + offset, bit_ofs, bit_len);
set_rec_bits(bits, bit_ptr, bit_ofs, bit_len);
}
Field::set_default(); Field::set_default();
} }
......
...@@ -1488,6 +1488,13 @@ class Field_bit :public Field { ...@@ -1488,6 +1488,13 @@ class Field_bit :public Field {
}; };
/**
BIT field represented as chars for non-MyISAM tables.
@todo The inheritance relationship is backwards since Field_bit is
an extended version of Field_bit_as_char and not the other way
around. Hence, we should refactor it to fix the hierarchy order.
*/
class Field_bit_as_char: public Field_bit { class Field_bit_as_char: public Field_bit {
public: public:
Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
......
...@@ -6578,10 +6578,13 @@ copy_extra_record_fields(TABLE *table, ...@@ -6578,10 +6578,13 @@ copy_extra_record_fields(TABLE *table,
case FIELD_TYPE_BIT: case FIELD_TYPE_BIT:
Field_bit *f= static_cast<Field_bit*>(*field_ptr); Field_bit *f= static_cast<Field_bit*>(*field_ptr);
my_ptrdiff_t const offset= table->record[1] - table->record[0]; if (f->bit_len > 0)
uchar const bits= {
get_rec_bits(f->bit_ptr + offset, f->bit_ofs, f->bit_len); my_ptrdiff_t const offset= table->record[1] - table->record[0];
set_rec_bits(bits, f->bit_ptr, f->bit_ofs, f->bit_len); uchar const bits=
get_rec_bits(f->bit_ptr + offset, f->bit_ofs, f->bit_len);
set_rec_bits(bits, f->bit_ptr, f->bit_ofs, f->bit_len);
}
break; break;
} }
} }
...@@ -6682,7 +6685,7 @@ replace_record(THD *thd, TABLE *table, ...@@ -6682,7 +6685,7 @@ replace_record(THD *thd, TABLE *table,
present on the master from table->record[1], if there are any. present on the master from table->record[1], if there are any.
*/ */
copy_extra_record_fields(table, master_reclength, master_fields); copy_extra_record_fields(table, master_reclength, master_fields);
/* /*
REPLACE is defined as either INSERT or DELETE + INSERT. If REPLACE is defined as either INSERT or DELETE + INSERT. If
possible, we can replace it with an UPDATE, but that will not possible, we can replace it with an UPDATE, but that will not
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment