diff --git a/mysql-test/suite/json/r/json_table.result b/mysql-test/suite/json/r/json_table.result index 8e22ba59531..991884c9f74 100644 --- a/mysql-test/suite/json/r/json_table.result +++ b/mysql-test/suite/json/r/json_table.result @@ -516,5 +516,11 @@ a b NULL NULL DROP VIEW v; # +# MDEV-25178 JSON_TABLE: ASAN use-after-poison in my_fill_8bit / Json_table_column::On_response::respond +# +SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON ERROR)) AS jt; +a +0 +# # 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 b1cea033fd9..29e9f0e8764 100644 --- a/mysql-test/suite/json/t/json_table.test +++ b/mysql-test/suite/json/t/json_table.test @@ -395,6 +395,11 @@ SHOW CREATE VIEW v; SELECT * FROM v; DROP VIEW v; +--echo # +--echo # MDEV-25178 JSON_TABLE: ASAN use-after-poison in my_fill_8bit / Json_table_column::On_response::respond +--echo # +SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON ERROR)) AS jt; + --echo # --echo # End of 10.6 tests --echo # diff --git a/sql/field.h b/sql/field.h index 457b6dfaecb..557b0aaffa4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1611,7 +1611,8 @@ public: virtual longlong val_time_packed(THD *thd); virtual const TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset() const= 0; - virtual void change_charset(const DTCollation &new_cs) {} + /* returns TRUE if the new charset differs. */ + virtual bool change_charset(const DTCollation &new_cs) { return FALSE; } virtual const DTCollation &dtcollation() const= 0; virtual CHARSET_INFO *charset_for_protocol(void) const { return binary() ? &my_charset_bin : charset(); } @@ -2110,11 +2111,16 @@ public: { return m_collation; } - void change_charset(const DTCollation &new_cs) override + bool change_charset(const DTCollation &new_cs) override { - field_length= (field_length * new_cs.collation->mbmaxlen) / - m_collation.collation->mbmaxlen; - m_collation= new_cs; + 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; } 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 0d0e3f203fc..7fb7ce969e5 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -811,7 +811,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= thd->variables.collation_server; + sql_f->charset= &my_charset_utf8mb4_bin; if (sql_f->prepare_stage1(thd, thd->mem_root, table->file, table->file->ha_table_flags())) @@ -1148,12 +1148,12 @@ 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(); - f->change_charset( - jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation); - - if (field_offset) + if (f->change_charset( + jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation) || + field_offset) { - f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit); + if (field_offset) + f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit); f->reset(); }