MDEV-24978 : SIGABRT in __libc_message
Keyvalue can be longer than REC_VERSION_56_MAX_INDEX_COL_LEN and this leads out-of-array reference. Use dynamic memory allocation using actual max length of key value.
This commit is contained in:
parent
ba7d86a659
commit
30dea4599e
@ -34,3 +34,31 @@ COUNT(f1) = 1000
|
|||||||
1
|
1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE ten;
|
DROP TABLE ten;
|
||||||
|
connection node_1;
|
||||||
|
SET @value=REPEAT (1,5001);
|
||||||
|
CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
|
||||||
|
INSERT IGNORE INTO t VALUES(@value);
|
||||||
|
Warnings:
|
||||||
|
Warning 1265 Data truncated for column 'a' at row 1
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
connection node_2;
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
connection node_1;
|
||||||
|
DROP TABLE t;
|
||||||
|
CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
|
||||||
|
INSERT IGNORE INTO t VALUES(@value);
|
||||||
|
Warnings:
|
||||||
|
Warning 1265 Data truncated for column 'a' at row 1
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
connection node_2;
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
1
|
||||||
|
connection node_1;
|
||||||
|
DROP TABLE t;
|
||||||
|
@ -60,3 +60,26 @@ SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE ten;
|
DROP TABLE ten;
|
||||||
|
#
|
||||||
|
# MDEV-24978 : SIGABRT in __libc_message
|
||||||
|
#
|
||||||
|
--connection node_1
|
||||||
|
SET @value=REPEAT (1,5001);
|
||||||
|
CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
|
||||||
|
INSERT IGNORE INTO t VALUES(@value);
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
|
||||||
|
--connection node_1
|
||||||
|
DROP TABLE t;
|
||||||
|
CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
|
||||||
|
INSERT IGNORE INTO t VALUES(@value);
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
|
||||||
|
--connection node_1
|
||||||
|
DROP TABLE t;
|
||||||
|
@ -6730,8 +6730,8 @@ wsrep_innobase_mysql_sort(
|
|||||||
case MYSQL_TYPE_LONG_BLOB:
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
case MYSQL_TYPE_VARCHAR:
|
case MYSQL_TYPE_VARCHAR:
|
||||||
{
|
{
|
||||||
uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
|
uchar *tmp_str;
|
||||||
uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN;
|
uint tmp_length;
|
||||||
|
|
||||||
/* Use the charset number to pick the right charset struct for
|
/* Use the charset number to pick the right charset struct for
|
||||||
the comparison. Since the MySQL function get_charset may be
|
the comparison. Since the MySQL function get_charset may be
|
||||||
@ -6754,7 +6754,11 @@ wsrep_innobase_mysql_sort(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(str_length <= tmp_length);
|
// Note that strnxfrm may change length of string
|
||||||
|
tmp_length= charset->coll->strnxfrmlen(charset, str_length);
|
||||||
|
tmp_length= ut_max(str_length, tmp_length) + 1;
|
||||||
|
tmp_str= static_cast<uchar *>(ut_malloc_nokey(tmp_length));
|
||||||
|
ut_ad(str_length <= tmp_length);
|
||||||
memcpy(tmp_str, str, str_length);
|
memcpy(tmp_str, str, str_length);
|
||||||
|
|
||||||
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
|
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
|
||||||
@ -6778,6 +6782,7 @@ wsrep_innobase_mysql_sort(
|
|||||||
ret_length = tmp_length;
|
ret_length = tmp_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_free(tmp_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_DECIMAL :
|
case MYSQL_TYPE_DECIMAL :
|
||||||
@ -7129,7 +7134,7 @@ wsrep_store_key_val_for_row(
|
|||||||
THD* thd,
|
THD* thd,
|
||||||
TABLE* table,
|
TABLE* table,
|
||||||
uint keynr, /*!< in: key number */
|
uint keynr, /*!< in: key number */
|
||||||
char* buff, /*!< in/out: buffer for the key value (in MySQL
|
uchar* buff, /*!< in/out: buffer for the key value (in MySQL
|
||||||
format) */
|
format) */
|
||||||
uint buff_len,/*!< in: buffer length */
|
uint buff_len,/*!< in: buffer length */
|
||||||
const uchar* record,
|
const uchar* record,
|
||||||
@ -7138,7 +7143,7 @@ wsrep_store_key_val_for_row(
|
|||||||
KEY* key_info = table->key_info + keynr;
|
KEY* key_info = table->key_info + keynr;
|
||||||
KEY_PART_INFO* key_part = key_info->key_part;
|
KEY_PART_INFO* key_part = key_info->key_part;
|
||||||
KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts;
|
KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts;
|
||||||
char* buff_start = buff;
|
uchar* buff_start = buff;
|
||||||
enum_field_types mysql_type;
|
enum_field_types mysql_type;
|
||||||
Field* field;
|
Field* field;
|
||||||
uint buff_space = buff_len;
|
uint buff_space = buff_len;
|
||||||
@ -7150,7 +7155,8 @@ wsrep_store_key_val_for_row(
|
|||||||
|
|
||||||
for (; key_part != end; key_part++) {
|
for (; key_part != end; key_part++) {
|
||||||
|
|
||||||
uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'};
|
uchar *sorted=NULL;
|
||||||
|
uint max_len=0;
|
||||||
ibool part_is_null = FALSE;
|
ibool part_is_null = FALSE;
|
||||||
|
|
||||||
if (key_part->null_bit) {
|
if (key_part->null_bit) {
|
||||||
@ -7229,10 +7235,14 @@ wsrep_store_key_val_for_row(
|
|||||||
true_len = key_len;
|
true_len = key_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_len= true_len;
|
||||||
|
sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
|
||||||
memcpy(sorted, data, true_len);
|
memcpy(sorted, data, true_len);
|
||||||
true_len = wsrep_innobase_mysql_sort(
|
true_len = wsrep_innobase_mysql_sort(
|
||||||
mysql_type, cs->number, sorted, true_len,
|
mysql_type, cs->number, sorted, true_len,
|
||||||
REC_VERSION_56_MAX_INDEX_COL_LEN);
|
max_len);
|
||||||
|
ut_ad(true_len <= max_len);
|
||||||
|
|
||||||
if (wsrep_protocol_version > 1) {
|
if (wsrep_protocol_version > 1) {
|
||||||
/* Note that we always reserve the maximum possible
|
/* Note that we always reserve the maximum possible
|
||||||
length of the true VARCHAR in the key value, though
|
length of the true VARCHAR in the key value, though
|
||||||
@ -7317,11 +7327,13 @@ wsrep_store_key_val_for_row(
|
|||||||
true_len = key_len;
|
true_len = key_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_len= true_len;
|
||||||
|
sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
|
||||||
memcpy(sorted, blob_data, true_len);
|
memcpy(sorted, blob_data, true_len);
|
||||||
true_len = wsrep_innobase_mysql_sort(
|
true_len = wsrep_innobase_mysql_sort(
|
||||||
mysql_type, cs->number, sorted, true_len,
|
mysql_type, cs->number, sorted, true_len,
|
||||||
REC_VERSION_56_MAX_INDEX_COL_LEN);
|
max_len);
|
||||||
|
ut_ad(true_len <= max_len);
|
||||||
|
|
||||||
/* Note that we always reserve the maximum possible
|
/* Note that we always reserve the maximum possible
|
||||||
length of the BLOB prefix in the key value. */
|
length of the BLOB prefix in the key value. */
|
||||||
@ -7397,10 +7409,14 @@ wsrep_store_key_val_for_row(
|
|||||||
cs->mbmaxlen),
|
cs->mbmaxlen),
|
||||||
&error);
|
&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_len= true_len;
|
||||||
|
sorted= static_cast<uchar *>(ut_malloc_nokey(max_len+1));
|
||||||
memcpy(sorted, src_start, true_len);
|
memcpy(sorted, src_start, true_len);
|
||||||
true_len = wsrep_innobase_mysql_sort(
|
true_len = wsrep_innobase_mysql_sort(
|
||||||
mysql_type, cs->number, sorted, true_len,
|
mysql_type, cs->number, sorted, true_len,
|
||||||
REC_VERSION_56_MAX_INDEX_COL_LEN);
|
max_len);
|
||||||
|
ut_ad(true_len <= max_len);
|
||||||
|
|
||||||
if (true_len > buff_space) {
|
if (true_len > buff_space) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
@ -7415,6 +7431,11 @@ wsrep_store_key_val_for_row(
|
|||||||
buff += true_len;
|
buff += true_len;
|
||||||
buff_space -= true_len;
|
buff_space -= true_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sorted) {
|
||||||
|
ut_free(sorted);
|
||||||
|
sorted= NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(buff <= buff_start + buff_len);
|
ut_a(buff <= buff_start + buff_len);
|
||||||
@ -10492,7 +10513,7 @@ wsrep_append_key(
|
|||||||
trx_t *trx,
|
trx_t *trx,
|
||||||
TABLE_SHARE *table_share,
|
TABLE_SHARE *table_share,
|
||||||
TABLE *table,
|
TABLE *table,
|
||||||
const char* key,
|
const uchar* key,
|
||||||
uint16_t key_len,
|
uint16_t key_len,
|
||||||
wsrep_key_type key_type /*!< in: access type of this key
|
wsrep_key_type key_type /*!< in: access type of this key
|
||||||
(shared, exclusive, semi...) */
|
(shared, exclusive, semi...) */
|
||||||
@ -10596,8 +10617,8 @@ ha_innobase::wsrep_append_keys(
|
|||||||
|
|
||||||
if (wsrep_protocol_version == 0) {
|
if (wsrep_protocol_version == 0) {
|
||||||
uint len;
|
uint len;
|
||||||
char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
uchar keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
||||||
char *key = &keyval[0];
|
uchar *key = &keyval[0];
|
||||||
ibool is_null;
|
ibool is_null;
|
||||||
|
|
||||||
len = wsrep_store_key_val_for_row(
|
len = wsrep_store_key_val_for_row(
|
||||||
@ -10629,18 +10650,18 @@ ha_innobase::wsrep_append_keys(
|
|||||||
|
|
||||||
for (i=0; i<table->s->keys; ++i) {
|
for (i=0; i<table->s->keys; ++i) {
|
||||||
uint len;
|
uint len;
|
||||||
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
uchar keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
||||||
char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
uchar keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
|
||||||
char* key0 = &keyval0[1];
|
uchar* key0 = &keyval0[1];
|
||||||
char* key1 = &keyval1[1];
|
uchar* key1 = &keyval1[1];
|
||||||
KEY* key_info = table->key_info + i;
|
KEY* key_info = table->key_info + i;
|
||||||
ibool is_null;
|
ibool is_null;
|
||||||
|
|
||||||
dict_index_t* idx = innobase_get_index(i);
|
dict_index_t* idx = innobase_get_index(i);
|
||||||
dict_table_t* tab = (idx) ? idx->table : NULL;
|
dict_table_t* tab = (idx) ? idx->table : NULL;
|
||||||
|
|
||||||
keyval0[0] = (char)i;
|
keyval0[0] = (uchar)i;
|
||||||
keyval1[0] = (char)i;
|
keyval1[0] = (uchar)i;
|
||||||
|
|
||||||
if (!tab) {
|
if (!tab) {
|
||||||
WSREP_WARN("MariaDB-InnoDB key mismatch %s %s",
|
WSREP_WARN("MariaDB-InnoDB key mismatch %s %s",
|
||||||
@ -10698,7 +10719,7 @@ ha_innobase::wsrep_append_keys(
|
|||||||
|
|
||||||
wsrep_calc_row_hash(digest, record0, table, m_prebuilt, thd);
|
wsrep_calc_row_hash(digest, record0, table, m_prebuilt, thd);
|
||||||
if ((rcode = wsrep_append_key(thd, trx, table_share, table,
|
if ((rcode = wsrep_append_key(thd, trx, table_share, table,
|
||||||
(const char*) digest, 16,
|
(const uchar*) digest, 16,
|
||||||
key_type))) {
|
key_type))) {
|
||||||
DBUG_RETURN(rcode);
|
DBUG_RETURN(rcode);
|
||||||
}
|
}
|
||||||
@ -10708,7 +10729,7 @@ ha_innobase::wsrep_append_keys(
|
|||||||
digest, record1, table, m_prebuilt, thd);
|
digest, record1, table, m_prebuilt, thd);
|
||||||
if ((rcode = wsrep_append_key(thd, trx, table_share,
|
if ((rcode = wsrep_append_key(thd, trx, table_share,
|
||||||
table,
|
table,
|
||||||
(const char*) digest,
|
(const uchar*) digest,
|
||||||
16, key_type))) {
|
16, key_type))) {
|
||||||
DBUG_RETURN(rcode);
|
DBUG_RETURN(rcode);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user