MDEV-21589 AddressSanitizer: memcpy-param-overlap in Static_binary_string::q_append or String::append

Item_func_concat_ws::val_str():
- collects the result into the string "str" passed as a parameter.
- calls val_str(&tmp_buffer) to get arguments.

At some point due to heuristic it decides to swap the buffers:
- collect the result into &tmp_buffer
- call val_str(str) to get arguments

Item_func_password::val_str_ascii() returns a String pointing to its
member tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1].

As a result, it's possible that both str and tmp_buffer in
Item_func_concat_ws::val_str() point to Item_func_password::tmp_value.
Then, memcmp() called on overlapping memory fragrments.

Fixing Item_func_password::val_str_ascii() to use Item::copy()
instead of Item::set().
This commit is contained in:
Alexander Barkov 2024-12-03 14:03:17 +04:00 committed by Oleksandr Byelkin
parent 54c1031b74
commit d1f42fc80f
3 changed files with 35 additions and 2 deletions

View File

@ -287,3 +287,20 @@ SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT MAKE_SET(3,t,t) t2 FROM t1) sub;
c2
abcdefghi,abcdefghi-abcdefghi,abcdefghi
DROP TABLE t1;
# Start of 10.5 tests
#
# MDEV-13120 Wrong results with MAKE_SET() and subquery
#
CREATE TABLE t1 (a DATE, b DATETIME, c VARCHAR(8));
INSERT INTO t1 VALUES
('1996-03-06','1985-11-16 08:00:46','foo'),
('2028-08-26','1900-01-01 00:00:00','bar'),
('1973-05-04','1900-01-01 00:00:00','qux');
SELECT CONCAT_WS(' ', a, b, PASSWORD(c)) AS f FROM t1 GROUP BY f WITH ROLLUP;
f
1973-05-04 1900-01-01 00:00:00 *6D720C5AAB5096E70AA751206B45B484E5E0121F
1996-03-06 1985-11-16 08:00:46 *F3A2A51A9B0F2BE2468926B4132313728C250DBF
2028-08-26 1900-01-01 00:00:00 *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB
NULL
DROP TABLE t1;
# End of 10.5 tests

View File

@ -265,3 +265,19 @@ CREATE TABLE t1 (t VARCHAR(10) CHARSET latin1);
INSERT INTO t1 VALUES('abcdefghi');
SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT MAKE_SET(3,t,t) t2 FROM t1) sub;
DROP TABLE t1;
--echo # Start of 10.5 tests
--echo #
--echo # MDEV-13120 Wrong results with MAKE_SET() and subquery
--echo #
CREATE TABLE t1 (a DATE, b DATETIME, c VARCHAR(8));
INSERT INTO t1 VALUES
('1996-03-06','1985-11-16 08:00:46','foo'),
('2028-08-26','1900-01-01 00:00:00','bar'),
('1973-05-04','1900-01-01 00:00:00','qux');
SELECT CONCAT_WS(' ', a, b, PASSWORD(c)) AS f FROM t1 GROUP BY f WITH ROLLUP;
DROP TABLE t1;
--echo # End of 10.5 tests

View File

@ -2241,7 +2241,7 @@ String *Item_func_password::val_str_ascii(String *str)
if (args[0]->null_value || res->length() == 0)
return make_empty_result(str);
my_make_scrambled_password(tmp_value, res->ptr(), res->length());
str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1);
str->copy(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1);
break;
case OLD:
if ((null_value=args[0]->null_value))
@ -2249,7 +2249,7 @@ String *Item_func_password::val_str_ascii(String *str)
if (res->length() == 0)
return make_empty_result(str);
my_make_scrambled_password_323(tmp_value, res->ptr(), res->length());
str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, &my_charset_latin1);
str->copy(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, &my_charset_latin1);
break;
default:
DBUG_ASSERT(0);