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.
This commit is contained in:
Alexander Barkov 2024-11-06 10:21:08 +04:00
parent f39217da0c
commit fdb6db6b47
3 changed files with 39 additions and 12 deletions

View file

@ -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
#

View file

@ -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 #

View file

@ -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<STRING_BUFFER_USUAL_SIZE> 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;
}