summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2021-03-23 13:23:37 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2021-04-21 10:21:44 +0400
commit46d592a047a6a9a062e07fe511a6164fd5ccfc22 (patch)
tree4ed63ef77a600cf81de77c5c9df568bfab4e0ab2
parent0eda81e4d964898db271e08a68ef9ea1760913e0 (diff)
downloadmariadb-git-46d592a047a6a9a062e07fe511a6164fd5ccfc22.tar.gz
MDEV-25188 JSON_TABLE: ASAN use-after-poison in Field_long::reset / Table_function_json_table::setup or malloc(): invalid size.
MDEV-25192 JSON_TABLE: ASAN use-after-poison in field_conv_memcpy / Create_tmp_table::finalize upon query with derived table.
-rw-r--r--mysql-test/suite/json/r/json_table.result14
-rw-r--r--mysql-test/suite/json/t/json_table.test12
-rw-r--r--sql/field.h15
-rw-r--r--sql/json_table.cc22
4 files changed, 43 insertions, 20 deletions
diff --git a/mysql-test/suite/json/r/json_table.result b/mysql-test/suite/json/r/json_table.result
index 991884c9f74..aa3e56f62db 100644
--- a/mysql-test/suite/json/r/json_table.result
+++ b/mysql-test/suite/json/r/json_table.result
@@ -522,5 +522,19 @@ SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON E
a
0
#
+# MDEV-25188 JSON_TABLE: ASAN use-after-poison in Field_long::reset / Table_function_json_table::setup or malloc(): invalid size.
+#
+SELECT * FROM JSON_TABLE(CONVERT('{"x":1}' USING utf8mb4), '$' COLUMNS(a INT PATH '$', b CHAR(64) PATH '$.*', c INT EXISTS PATH '$**.*')) AS jt;
+a b c
+NULL 1 1
+#
+# 25192 JSON_TABLE: ASAN use-after-poison in field_conv_memcpy / Create_tmp_table::finalize upon query with derived table.
+#
+SET NAMES utf8;
+SELECT * FROM ( SELECT * FROM JSON_TABLE('{}', '$' COLUMNS( a BINARY(12) PATH '$.*', b VARCHAR(40) PATH '$[*]', c VARCHAR(8) PATH '$**.*')) AS jt ) AS sq;
+a b c
+NULL NULL NULL
+SET NAMES default;
+#
# End of 10.6 tests
#
diff --git a/mysql-test/suite/json/t/json_table.test b/mysql-test/suite/json/t/json_table.test
index 29e9f0e8764..fd6835011ef 100644
--- a/mysql-test/suite/json/t/json_table.test
+++ b/mysql-test/suite/json/t/json_table.test
@@ -401,5 +401,17 @@ DROP VIEW v;
SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON ERROR)) AS jt;
--echo #
+--echo # MDEV-25188 JSON_TABLE: ASAN use-after-poison in Field_long::reset / Table_function_json_table::setup or malloc(): invalid size.
+--echo #
+SELECT * FROM JSON_TABLE(CONVERT('{"x":1}' USING utf8mb4), '$' COLUMNS(a INT PATH '$', b CHAR(64) PATH '$.*', c INT EXISTS PATH '$**.*')) AS jt;
+
+--echo #
+--echo # 25192 JSON_TABLE: ASAN use-after-poison in field_conv_memcpy / Create_tmp_table::finalize upon query with derived table.
+--echo #
+SET NAMES utf8;
+SELECT * FROM ( SELECT * FROM JSON_TABLE('{}', '$' COLUMNS( a BINARY(12) PATH '$.*', b VARCHAR(40) PATH '$[*]', c VARCHAR(8) PATH '$**.*')) AS jt ) AS sq;
+SET NAMES default;
+
+--echo #
--echo # End of 10.6 tests
--echo #
diff --git a/sql/field.h b/sql/field.h
index 557b0aaffa4..b312b10881f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1612,7 +1612,7 @@ public:
virtual const TYPELIB *get_typelib() const { return NULL; }
virtual CHARSET_INFO *charset() const= 0;
/* returns TRUE if the new charset differs. */
- virtual bool change_charset(const DTCollation &new_cs) { return FALSE; }
+ virtual void change_charset(const DTCollation &new_cs) {}
virtual const DTCollation &dtcollation() const= 0;
virtual CHARSET_INFO *charset_for_protocol(void) const
{ return binary() ? &my_charset_bin : charset(); }
@@ -2111,16 +2111,11 @@ public:
{
return m_collation;
}
- bool change_charset(const DTCollation &new_cs) override
+ void change_charset(const DTCollation &new_cs) override
{
- if (m_collation.collation != new_cs.collation)
- {
- field_length= (field_length * new_cs.collation->mbmaxlen) /
- m_collation.collation->mbmaxlen;
- m_collation= new_cs;
- return TRUE;
- }
- return FALSE;
+ field_length= (field_length * new_cs.collation->mbmaxlen) /
+ m_collation.collation->mbmaxlen;
+ m_collation= new_cs;
}
bool binary() const override { return field_charset() == &my_charset_bin; }
uint32 max_display_length() const override { return field_length; }
diff --git a/sql/json_table.cc b/sql/json_table.cc
index 7fb7ce969e5..6f6c270137a 100644
--- a/sql/json_table.cc
+++ b/sql/json_table.cc
@@ -718,7 +718,10 @@ bool Create_json_table::finalize(THD *thd, TABLE *table,
m_null_count & 7);
m_null_count+= (field->field_length & 7);
}
- field->reset();
+ /*
+ Here we'd call the field->reset(), but we're doing it later
+ in Table_function_json_table::setup as we define charsets there.
+ */
/*
Test if there is a default field value. The test for ->ptr is to skip
@@ -811,7 +814,7 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
*/
sql_f->length= sql_f->char_length;
if (!(jc->m_explicit_cs= sql_f->charset))
- sql_f->charset= &my_charset_utf8mb4_bin;
+ sql_f->charset= &my_charset_utf8mb4_general_ci;
if (sql_f->prepare_stage1(thd, thd->mem_root, table->file,
table->file->ha_table_flags()))
@@ -1148,14 +1151,13 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table,
Json_table_column *jc= jc_i++;
uint32 old_pack_length= f->pack_length();
- if (f->change_charset(
- jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation) ||
- field_offset)
- {
- if (field_offset)
- f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit);
- f->reset();
- }
+ f->change_charset(
+ jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation);
+
+ if (field_offset)
+ f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit);
+
+ f->reset();
field_offset= (field_offset + f->pack_length()) - old_pack_length;