summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Gupta <varun.gupta@mariadb.com>2020-05-18 10:31:17 +0530
committerVarun Gupta <varun.gupta@mariadb.com>2020-05-18 10:31:17 +0530
commite59e7723f6cc5b7ca6c6b4ee9f05f0cd192c56ad (patch)
treecdc451aa83bc7e2e140f386c6bc3766b499facc8
parent5d85bc08c6412d067a69d2c1354a10f9a803b332 (diff)
downloadmariadb-git-10.5-mdev22509.tar.gz
MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null10.5-mdev22509
-rw-r--r--plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result14
-rw-r--r--plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test10
-rw-r--r--plugin/type_inet/sql_type_inet.cc1
-rw-r--r--sql/field.cc31
-rw-r--r--sql/field.h22
-rw-r--r--sql/sql_statistics.cc38
6 files changed, 90 insertions, 26 deletions
diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result
index 6d84d105c99..1cbedad1c3c 100644
--- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result
+++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result
@@ -13,5 +13,19 @@ test.t1 analyze status OK
INSERT INTO t1 VALUES ('3::3');
DROP TABLE t1;
#
+# MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null
+#
+CREATE TABLE t1 (a INT, b INET6 NOT NULL);
+INSERT INTO t1 VALUES (1,'::'),(2,'::');
+ANALYZE TABLE t1 PERSISTENT FOR ALL;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+SELECT t1.a from t1;
+a
+1
+2
+DROP TABLE t1;
+#
# End of 10.5 tests
#
diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test
index fb092db6bc4..063581b12f5 100644
--- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test
+++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test
@@ -15,5 +15,15 @@ INSERT INTO t1 VALUES ('3::3');
DROP TABLE t1;
--echo #
+--echo # MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null
+--echo #
+
+CREATE TABLE t1 (a INT, b INET6 NOT NULL);
+INSERT INTO t1 VALUES (1,'::'),(2,'::');
+ANALYZE TABLE t1 PERSISTENT FOR ALL;
+SELECT t1.a from t1;
+DROP TABLE t1;
+
+--echo #
--echo # End of 10.5 tests
--echo #
diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc
index 29234aa4a56..a8639656a15 100644
--- a/plugin/type_inet/sql_type_inet.cc
+++ b/plugin/type_inet/sql_type_inet.cc
@@ -1000,6 +1000,7 @@ public:
return StringPack::packed_col_length(data_ptr, length);
}
+
/**********/
uint size_of() const override { return sizeof(*this); }
};
diff --git a/sql/field.cc b/sql/field.cc
index 6234de43ec8..1184d801a37 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1967,6 +1967,37 @@ int Field::store_timestamp_dec(const timeval &ts, uint dec)
return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec);
}
+
+int Field::store_to_statistical_minmax_field(Field *field, String *val)
+{
+ val_str(val);
+ size_t length= Well_formed_prefix(val->charset(), val->ptr(),
+ MY_MIN(val->length(), field->field_length)).length();
+ return field->store(str->ptr(), length, &my_charset_bin);
+}
+
+
+int Field::store_from_statistical_minmax_field(Field *stat_field, String *str)
+{
+ stat_field->val_str(str);
+ return store_text(str->ptr(), str->length(), &my_charset_bin);
+}
+
+
+int Field_bit::store_to_statistical_minmax_field(Field *field, String *str)
+{
+ longlong nr= val_int();
+ return field->store(nr, TRUE);
+}
+
+
+int Field_bit::store_from_statistical_minmax_field(Field *stat_field,
+ String *str __attribute__((unused)))
+{
+ return store(stat_field->val_int(), TRUE);
+}
+
+
/**
Pack the field into a format suitable for storage and transfer.
diff --git a/sql/field.h b/sql/field.h
index d709a84e0fe..358eb3939dc 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -977,6 +977,26 @@ public:
DBUG_ASSERT(ls.length < UINT_MAX32);
return store(ls.str, (uint) ls.length, cs);
}
+
+ /*
+ @brief
+ Store minimum/maximum value of a column in the statistics table.
+ @param
+ field statistical table field
+ str value buffer
+ */
+ virtual int store_to_statistical_minmax_field(Field *field, String *str);
+
+ /*
+ @brief
+ Store minimum/maximum value of a column from the statistical table.
+
+ @param
+ field statistical table field
+ str value buffer
+ */
+ virtual int store_from_statistical_minmax_field(Field *field, String *str);
+
virtual double val_real()=0;
virtual longlong val_int()=0;
/*
@@ -4946,6 +4966,8 @@ public:
static_cast<uint16>((field_length & 7) |
((field_length / 8) << 8)), 2);
}
+ int store_to_statistical_minmax_field(Field *fld, String *str) override;
+ int store_from_statistical_minmax_field(Field *fld, String *str) override;
private:
size_t do_last_null_byte() const override;
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 55e8e52c052..ef9d4a1599c 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1025,6 +1025,7 @@ public:
char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_bin);
my_bitmap_map *old_map;
+ Field *fld= NULL;
old_map= dbug_tmp_use_all_columns(stat_table, stat_table->read_set);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
@@ -1037,26 +1038,12 @@ public:
stat_field->set_notnull();
switch (i) {
case COLUMN_STAT_MIN_VALUE:
- if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->min_value->val_int(),true);
- else
- {
- table_field->collected_stats->min_value->val_str(&val);
- size_t length= Well_formed_prefix(val.charset(), val.ptr(),
- MY_MIN(val.length(), stat_field->field_length)).length();
- stat_field->store(val.ptr(), length, &my_charset_bin);
- }
+ fld= table_field->collected_stats->min_value;
+ fld->store_to_statistical_minmax_field(stat_field, &val);
break;
case COLUMN_STAT_MAX_VALUE:
- if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->max_value->val_int(),true);
- else
- {
- table_field->collected_stats->max_value->val_str(&val);
- size_t length= Well_formed_prefix(val.charset(), val.ptr(),
- MY_MIN(val.length(), stat_field->field_length)).length();
- stat_field->store(val.ptr(), length, &my_charset_bin);
- }
+ fld= table_field->collected_stats->max_value;
+ fld->store_to_statistical_minmax_field(stat_field, &val);
break;
case COLUMN_STAT_NULLS_RATIO:
stat_field->store(table_field->collected_stats->get_nulls_ratio());
@@ -1118,6 +1105,7 @@ public:
{
char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_bin);
+ Field *field= NULL;
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++)
{
@@ -1134,16 +1122,14 @@ public:
switch (i) {
case COLUMN_STAT_MIN_VALUE:
- table_field->read_stats->min_value->set_notnull();
- stat_field->val_str(&val);
- table_field->read_stats->min_value->store(val.ptr(), val.length(),
- &my_charset_bin);
+ field= table_field->read_stats->min_value;
+ field->set_notnull();
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
case COLUMN_STAT_MAX_VALUE:
- table_field->read_stats->max_value->set_notnull();
- stat_field->val_str(&val);
- table_field->read_stats->max_value->store(val.ptr(), val.length(),
- &my_charset_bin);
+ field= table_field->read_stats->min_value;
+ field->set_notnull();
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
case COLUMN_STAT_NULLS_RATIO:
table_field->read_stats->set_nulls_ratio(stat_field->val_real());