From b1f69b48ef4ff2354b8b7cd9889a3ab02dea548c Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Tue, 20 Mar 2007 14:13:07 +0100 Subject: [PATCH] BUG#26969: Field_bit::pack() and Field_bit::unpack() does not work correctly Fixing code for Field_bit packing and unpacking to work with arbitrary pointers instead of requiring Field::ptr --- sql/field.cc | 34 ++++++++++++++++++++++++++++++---- sql/sql_class.cc | 4 +--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 488a5d591a3..ecfdb46ac02 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8505,9 +8505,28 @@ char *Field_bit::pack(char *to, const char *from, uint max_length) { DBUG_ASSERT(max_length); uint length; - if (bit_len) + if (bit_len > 0) { - uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); + /* + We have the following: + + ptr Points into a field in record R1 + from Points to a field in a record R2 + bit_ptr Points to the byte (in the null bytes) that holds the + odd bits of R1 + from_bitp Points to the byte that holds the odd bits of R2 + + We have the following: + + ptr - bit_ptr = from - from_bitp + + We want to isolate 'from_bitp', so this gives: + + ptr - bit_ptr - from = - from_bitp + - ptr + bit_ptr + from = from_bitp + bit_ptr + from - ptr = from_bitp + */ + uchar bits= get_rec_bits(bit_ptr + (from - ptr), bit_ofs, bit_len); *to++= bits; } length= min(bytes_in_rec, max_length - (bit_len > 0)); @@ -8518,9 +8537,16 @@ char *Field_bit::pack(char *to, const char *from, uint max_length) const char *Field_bit::unpack(char *to, const char *from) { - if (bit_len) + if (bit_len > 0) { - set_rec_bits(*from, bit_ptr, bit_ofs, bit_len); + /* + set_rec_bits is a macro, don't put the post-increment in the + argument since that might cause strange side-effects. + + For the choice of the second argument, see the explanation for + Field_bit::pack(). + */ + set_rec_bits(*from, bit_ptr + (to - ptr), bit_ofs, bit_len); from++; } memcpy(to, from, bytes_in_rec); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4ca15a8a5f9..0b87a4185dd 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2619,9 +2619,7 @@ THD::pack_row(TABLE *table, MY_BITMAP const* cols, /* We only store the data of the field if it is non-null */ - field->move_field_offset(offset); - pack_ptr= (byte*)field->pack((char *) pack_ptr, field->ptr); - field->move_field_offset(-offset); + pack_ptr= (byte*)field->pack((char *) pack_ptr, field->ptr + offset); } null_mask <<= 1;