From fdb6db6b47f1825eabffde76c29d9b94545f1ef4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 6 Nov 2024 10:21:08 +0400 Subject: [PATCH] MDEV-29462 ASAN: heap-use-after-free in Binary_string::copy on DO CONVERT Item_char_typecast::val_str_generic() uses Item::str_value as a buffer. Item::val_str_ascii() also used Item::str_value as a buffer. As a result, str_value tried to copy to itself. Fixing val_str_ascii() to use a local buffer instead of str_value. --- mysql-test/main/func_misc.result | 13 +++++++++++++ mysql-test/main/func_misc.test | 10 ++++++++++ sql/item.cc | 28 ++++++++++++++++------------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/mysql-test/main/func_misc.result b/mysql-test/main/func_misc.result index a6869296090..59e62af37f2 100644 --- a/mysql-test/main/func_misc.result +++ b/mysql-test/main/func_misc.result @@ -1743,5 +1743,18 @@ count(*) 0 drop table t1; # +# MDEV-29462 ASAN: heap-use-after-free in Binary_string::copy on DO CONVERT +# +DO CONVERT (INET_ATON (CAST(LEFT (-1,1) as BINARY (30))) USING utf8); +DO FROM_BASE64(CAST((MID(UUID(),20,64)) AS BINARY (55))); +Warnings: +Warning 1958 Bad base64 data as position 4 +DO FROM_BASE64(CAST((MID(17653,ROW('-688:20:162697', (NULL))>=ROW(('*.)$'),(0xc254b6)),1)) AS BINARY (34))); +Warnings: +Warning 1958 Bad base64 data as position 1 +DO FROM_BASE64(CAST(LEFT (-1,1) as BINARY (30))); +Warnings: +Warning 1958 Bad base64 data as position 0 +# # End of 10.5 tests # diff --git a/mysql-test/main/func_misc.test b/mysql-test/main/func_misc.test index 498c8a94df9..70581d55067 100644 --- a/mysql-test/main/func_misc.test +++ b/mysql-test/main/func_misc.test @@ -1375,6 +1375,16 @@ SELECT r as r1, r FROM cte; select count(*) from t1 where r1!=r; drop table t1; +--echo # +--echo # MDEV-29462 ASAN: heap-use-after-free in Binary_string::copy on DO CONVERT +--echo # + +DO CONVERT (INET_ATON (CAST(LEFT (-1,1) as BINARY (30))) USING utf8); +DO FROM_BASE64(CAST((MID(UUID(),20,64)) AS BINARY (55))); +DO FROM_BASE64(CAST((MID(17653,ROW('-688:20:162697', (NULL))>=ROW(('*.)$'),(0xc254b6)),1)) AS BINARY (34))); +DO FROM_BASE64(CAST(LEFT (-1,1) as BINARY (30))); + --echo # --echo # End of 10.5 tests --echo # + diff --git a/sql/item.cc b/sql/item.cc index 439778f654c..dc27feb759a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -163,20 +163,24 @@ longlong Item::val_time_packed_result(THD *thd) String *Item::val_str_ascii(String *str) { DBUG_ASSERT(str != &str_value); - - uint errors; - String *res= val_str(&str_value); + + if (!(collation.collation->state & MY_CS_NONASCII)) + return val_str(str); + + /* + We cannot use str_value as a buffer here, + because val_str() can use it. Let's have a local buffer. + */ + StringBuffer tmp; + String *res= val_str(&tmp); + if (!res) return 0; - - if (!(res->charset()->state & MY_CS_NONASCII)) - str= res; - else - { - if ((null_value= str->copy(res->ptr(), res->length(), collation.collation, - &my_charset_latin1, &errors))) - return 0; - } + + uint errors; + if ((null_value= str->copy(res->ptr(), res->length(), collation.collation, + &my_charset_latin1, &errors))) + return 0; return str; }