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_index_t* new_index;
|
||||||
dict_field_t* field;
|
dict_field_t* field;
|
||||||
ulint fixed_size;
|
|
||||||
ulint trx_id_pos;
|
ulint trx_id_pos;
|
||||||
ulint i;
|
ulint i;
|
||||||
ibool* indexed;
|
ibool* indexed;
|
||||||
@ -1706,7 +1705,7 @@ dict_index_build_internal_clust(
|
|||||||
|
|
||||||
for (i = 0; i < trx_id_pos; i++) {
|
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_index_get_nth_col(new_index, i));
|
||||||
|
|
||||||
if (fixed_size == 0) {
|
if (fixed_size == 0) {
|
||||||
@ -1722,7 +1721,20 @@ dict_index_build_internal_clust(
|
|||||||
break;
|
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;
|
unsigned space:32;
|
||||||
/* space where the index tree is placed */
|
/* space where the index tree is placed */
|
||||||
unsigned page:32;/* index tree root page number */
|
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
|
in a clustered index record, if the fields
|
||||||
before it are known to be of a fixed size,
|
before it are known to be of a fixed size,
|
||||||
0 otherwise */
|
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;
|
unsigned n_user_defined_cols:10;
|
||||||
/* number of columns the user defined to
|
/* number of columns the user defined to
|
||||||
be in the index: in the internal
|
be in the index: in the internal
|
||||||
|
@ -1959,7 +1959,6 @@ dict_index_build_internal_clust(
|
|||||||
{
|
{
|
||||||
dict_index_t* new_index;
|
dict_index_t* new_index;
|
||||||
dict_field_t* field;
|
dict_field_t* field;
|
||||||
ulint fixed_size;
|
|
||||||
ulint trx_id_pos;
|
ulint trx_id_pos;
|
||||||
ulint i;
|
ulint i;
|
||||||
ibool* indexed;
|
ibool* indexed;
|
||||||
@ -2036,7 +2035,7 @@ dict_index_build_internal_clust(
|
|||||||
|
|
||||||
for (i = 0; i < trx_id_pos; i++) {
|
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_index_get_nth_col(new_index, i),
|
||||||
dict_table_is_comp(table));
|
dict_table_is_comp(table));
|
||||||
|
|
||||||
@ -2053,7 +2052,20 @@ dict_index_build_internal_clust(
|
|||||||
break;
|
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 */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
|
unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
|
||||||
DICT_UNIVERSAL, DICT_IBUF) */
|
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
|
in a clustered index record, if the fields
|
||||||
before it are known to be of a fixed size,
|
before it are known to be of a fixed size,
|
||||||
0 otherwise */
|
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;
|
unsigned n_user_defined_cols:10;
|
||||||
/*!< number of columns the user defined to
|
/*!< number of columns the user defined to
|
||||||
be in the index: in the internal
|
be in the index: in the internal
|
||||||
|
Loading…
x
Reference in New Issue
Block a user