Bug#14731482 UPDATE OR DELETE CORRUPTS A RECORD WITH A LONG PRIMARY KEY
We did not allocate enough bits for index->trx_id_offset, causing an UPDATE or DELETE of a table with a PRIMARY KEY longer than 1024 bytes to corrupt the PRIMARY KEY. dict_index_t: Allocate enough bits. dict_index_build_internal_clust(): Check for overflow of index->trx_id_offset. Trip a debug assertion when overflow occurs. rb:1380 approved by Jimmy Yang
This commit is contained in:
parent
540d0cd28e
commit
b06620868e
@ -1629,7 +1629,6 @@ dict_index_build_internal_clust(
|
||||
{
|
||||
dict_index_t* new_index;
|
||||
dict_field_t* field;
|
||||
ulint fixed_size;
|
||||
ulint trx_id_pos;
|
||||
ulint i;
|
||||
ibool* indexed;
|
||||
@ -1706,7 +1705,7 @@ dict_index_build_internal_clust(
|
||||
|
||||
for (i = 0; i < trx_id_pos; i++) {
|
||||
|
||||
fixed_size = dict_col_get_fixed_size(
|
||||
ulint fixed_size = dict_col_get_fixed_size(
|
||||
dict_index_get_nth_col(new_index, i));
|
||||
|
||||
if (fixed_size == 0) {
|
||||
@ -1722,7 +1721,20 @@ dict_index_build_internal_clust(
|
||||
break;
|
||||
}
|
||||
|
||||
new_index->trx_id_offset += (unsigned int) fixed_size;
|
||||
/* Add fixed_size to new_index->trx_id_offset.
|
||||
Because the latter is a bit-field, an overflow
|
||||
can theoretically occur. Check for it. */
|
||||
fixed_size += new_index->trx_id_offset;
|
||||
|
||||
new_index->trx_id_offset = fixed_size;
|
||||
|
||||
if (new_index->trx_id_offset != fixed_size) {
|
||||
/* Overflow. Pretend that this is a
|
||||
variable-length PRIMARY KEY. */
|
||||
ut_ad(0);
|
||||
new_index->trx_id_offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -196,10 +196,15 @@ struct dict_index_struct{
|
||||
unsigned space:32;
|
||||
/* space where the index tree is placed */
|
||||
unsigned page:32;/* index tree root page number */
|
||||
unsigned trx_id_offset:10;/* position of the the trx id column
|
||||
#define MAX_KEY_LENGTH_BITS 12
|
||||
unsigned trx_id_offset:MAX_KEY_LENGTH_BITS;
|
||||
/* position of the trx id column
|
||||
in a clustered index record, if the fields
|
||||
before it are known to be of a fixed size,
|
||||
0 otherwise */
|
||||
#if (1<<MAX_KEY_LENGTH_BITS) < MAX_KEY_LENGTH
|
||||
# error (1<<MAX_KEY_LENGTH_BITS) < MAX_KEY_LENGTH
|
||||
#endif
|
||||
unsigned n_user_defined_cols:10;
|
||||
/* number of columns the user defined to
|
||||
be in the index: in the internal
|
||||
|
@ -1959,7 +1959,6 @@ dict_index_build_internal_clust(
|
||||
{
|
||||
dict_index_t* new_index;
|
||||
dict_field_t* field;
|
||||
ulint fixed_size;
|
||||
ulint trx_id_pos;
|
||||
ulint i;
|
||||
ibool* indexed;
|
||||
@ -2036,7 +2035,7 @@ dict_index_build_internal_clust(
|
||||
|
||||
for (i = 0; i < trx_id_pos; i++) {
|
||||
|
||||
fixed_size = dict_col_get_fixed_size(
|
||||
ulint fixed_size = dict_col_get_fixed_size(
|
||||
dict_index_get_nth_col(new_index, i),
|
||||
dict_table_is_comp(table));
|
||||
|
||||
@ -2053,7 +2052,20 @@ dict_index_build_internal_clust(
|
||||
break;
|
||||
}
|
||||
|
||||
new_index->trx_id_offset += (unsigned int) fixed_size;
|
||||
/* Add fixed_size to new_index->trx_id_offset.
|
||||
Because the latter is a bit-field, an overflow
|
||||
can theoretically occur. Check for it. */
|
||||
fixed_size += new_index->trx_id_offset;
|
||||
|
||||
new_index->trx_id_offset = fixed_size;
|
||||
|
||||
if (new_index->trx_id_offset != fixed_size) {
|
||||
/* Overflow. Pretend that this is a
|
||||
variable-length PRIMARY KEY. */
|
||||
ut_ad(0);
|
||||
new_index->trx_id_offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -286,10 +286,15 @@ struct dict_index_struct{
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
|
||||
DICT_UNIVERSAL, DICT_IBUF) */
|
||||
unsigned trx_id_offset:10;/*!< position of the trx id column
|
||||
#define MAX_KEY_LENGTH_BITS 12
|
||||
unsigned trx_id_offset:MAX_KEY_LENGTH_BITS;
|
||||
/*!< position of the trx id column
|
||||
in a clustered index record, if the fields
|
||||
before it are known to be of a fixed size,
|
||||
0 otherwise */
|
||||
#if (1<<MAX_KEY_LENGTH_BITS) < MAX_KEY_LENGTH
|
||||
# error (1<<MAX_KEY_LENGTH_BITS) < MAX_KEY_LENGTH
|
||||
#endif
|
||||
unsigned n_user_defined_cols:10;
|
||||
/*!< number of columns the user defined to
|
||||
be in the index: in the internal
|
||||
|
Loading…
x
Reference in New Issue
Block a user