Skip to content

Commit 46d592a

Browse files
author
Alexey Botchkov
committed
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.
1 parent 0eda81e commit 46d592a

File tree

4 files changed

+43
-20
lines changed

4 files changed

+43
-20
lines changed

mysql-test/suite/json/r/json_table.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,5 +522,19 @@ SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON E
522522
a
523523
0
524524
#
525+
# MDEV-25188 JSON_TABLE: ASAN use-after-poison in Field_long::reset / Table_function_json_table::setup or malloc(): invalid size.
526+
#
527+
SELECT * FROM JSON_TABLE(CONVERT('{"x":1}' USING utf8mb4), '$' COLUMNS(a INT PATH '$', b CHAR(64) PATH '$.*', c INT EXISTS PATH '$**.*')) AS jt;
528+
a b c
529+
NULL 1 1
530+
#
531+
# 25192 JSON_TABLE: ASAN use-after-poison in field_conv_memcpy / Create_tmp_table::finalize upon query with derived table.
532+
#
533+
SET NAMES utf8;
534+
SELECT * FROM ( SELECT * FROM JSON_TABLE('{}', '$' COLUMNS( a BINARY(12) PATH '$.*', b VARCHAR(40) PATH '$[*]', c VARCHAR(8) PATH '$**.*')) AS jt ) AS sq;
535+
a b c
536+
NULL NULL NULL
537+
SET NAMES default;
538+
#
525539
# End of 10.6 tests
526540
#

mysql-test/suite/json/t/json_table.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,18 @@ DROP VIEW v;
400400
--echo #
401401
SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(a CHAR(100) PATH '$' DEFAULT "0" ON ERROR)) AS jt;
402402

403+
--echo #
404+
--echo # MDEV-25188 JSON_TABLE: ASAN use-after-poison in Field_long::reset / Table_function_json_table::setup or malloc(): invalid size.
405+
--echo #
406+
SELECT * FROM JSON_TABLE(CONVERT('{"x":1}' USING utf8mb4), '$' COLUMNS(a INT PATH '$', b CHAR(64) PATH '$.*', c INT EXISTS PATH '$**.*')) AS jt;
407+
408+
--echo #
409+
--echo # 25192 JSON_TABLE: ASAN use-after-poison in field_conv_memcpy / Create_tmp_table::finalize upon query with derived table.
410+
--echo #
411+
SET NAMES utf8;
412+
SELECT * FROM ( SELECT * FROM JSON_TABLE('{}', '$' COLUMNS( a BINARY(12) PATH '$.*', b VARCHAR(40) PATH '$[*]', c VARCHAR(8) PATH '$**.*')) AS jt ) AS sq;
413+
SET NAMES default;
414+
403415
--echo #
404416
--echo # End of 10.6 tests
405417
--echo #

sql/field.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,7 @@ class Field: public Value_source
16121612
virtual const TYPELIB *get_typelib() const { return NULL; }
16131613
virtual CHARSET_INFO *charset() const= 0;
16141614
/* returns TRUE if the new charset differs. */
1615-
virtual bool change_charset(const DTCollation &new_cs) { return FALSE; }
1615+
virtual void change_charset(const DTCollation &new_cs) {}
16161616
virtual const DTCollation &dtcollation() const= 0;
16171617
virtual CHARSET_INFO *charset_for_protocol(void) const
16181618
{ return binary() ? &my_charset_bin : charset(); }
@@ -2111,16 +2111,11 @@ class Field_str :public Field {
21112111
{
21122112
return m_collation;
21132113
}
2114-
bool change_charset(const DTCollation &new_cs) override
2114+
void change_charset(const DTCollation &new_cs) override
21152115
{
2116-
if (m_collation.collation != new_cs.collation)
2117-
{
2118-
field_length= (field_length * new_cs.collation->mbmaxlen) /
2119-
m_collation.collation->mbmaxlen;
2120-
m_collation= new_cs;
2121-
return TRUE;
2122-
}
2123-
return FALSE;
2116+
field_length= (field_length * new_cs.collation->mbmaxlen) /
2117+
m_collation.collation->mbmaxlen;
2118+
m_collation= new_cs;
21242119
}
21252120
bool binary() const override { return field_charset() == &my_charset_bin; }
21262121
uint32 max_display_length() const override { return field_length; }

sql/json_table.cc

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,10 @@ bool Create_json_table::finalize(THD *thd, TABLE *table,
718718
m_null_count & 7);
719719
m_null_count+= (field->field_length & 7);
720720
}
721-
field->reset();
721+
/*
722+
Here we'd call the field->reset(), but we're doing it later
723+
in Table_function_json_table::setup as we define charsets there.
724+
*/
722725

723726
/*
724727
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,
811814
*/
812815
sql_f->length= sql_f->char_length;
813816
if (!(jc->m_explicit_cs= sql_f->charset))
814-
sql_f->charset= &my_charset_utf8mb4_bin;
817+
sql_f->charset= &my_charset_utf8mb4_general_ci;
815818

816819
if (sql_f->prepare_stage1(thd, thd->mem_root, table->file,
817820
table->file->ha_table_flags()))
@@ -1148,14 +1151,13 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table,
11481151
Json_table_column *jc= jc_i++;
11491152
uint32 old_pack_length= f->pack_length();
11501153

1151-
if (f->change_charset(
1152-
jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation) ||
1153-
field_offset)
1154-
{
1155-
if (field_offset)
1156-
f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit);
1157-
f->reset();
1158-
}
1154+
f->change_charset(
1155+
jc->m_explicit_cs ? jc->m_explicit_cs : m_json->collation);
1156+
1157+
if (field_offset)
1158+
f->move_field(f->ptr + field_offset, f->null_ptr, f->null_bit);
1159+
1160+
f->reset();
11591161

11601162
field_offset= (field_offset + f->pack_length()) - old_pack_length;
11611163

0 commit comments

Comments
 (0)