mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-41496 OOB write with RPAD() crash and multi-byte charsets and uservar
item's charset is metadata, it's known at fix_fields and does not change later. user variables can violate this invariant if they're changed and used in the same query. Let's always wrap such variables in Item_func_conv_charset() to make sure the caller always gets the same fixed charset, no matter what the actual variable value is. Variables that aren't changed in the same query do not get this unnecessary conversion.
This commit is contained in:
@@ -5696,4 +5696,34 @@ a b a b
|
||||
1 1 1 1
|
||||
2 3 NULL NULL
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-41496 OOB write with RPAD() crash and multi-byte charsets
|
||||
#
|
||||
SET @p=_latin1'x';
|
||||
SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
LENGTH(RPAD(_latin1'a', 766, @p))
|
||||
766
|
||||
EXPLAIN EXTENDED SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select octet_length(rpad('a',766,convert(@`p` using ucs2))) AS `LENGTH(RPAD(_latin1'a', 766, @p))` where 1
|
||||
EXPLAIN EXTENDED SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p = CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select octet_length(rpad('a',766,@`p`)) AS `LENGTH(RPAD(_latin1'a', 766, @p))` where 1
|
||||
SET @p=_utf16'x';
|
||||
SELECT LENGTH(RPAD(_utf16'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONCAT(_latin1'ab', _latin1 0xD800, REPEAT(_latin1'z',1000))) IS NOT NULL;
|
||||
LENGTH(RPAD(_utf16'a', 766, @p))
|
||||
1532
|
||||
SET @p= _utf8mb3'b';
|
||||
SELECT HEX(CONCAT(_utf8mb3'a', @p)) FROM DUAL
|
||||
WHERE (@p := _ucs2 0x00FF) IS NOT NULL;
|
||||
HEX(CONCAT(_utf8mb3'a', @p))
|
||||
61C3BF
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -2633,4 +2633,26 @@ insert t1 values (1,1),(2,3);
|
||||
select * from t1 left join t1 t2 on (t1.a=t2.b) where quote(t2.b)>'';
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-41496 OOB write with RPAD() crash and multi-byte charsets
|
||||
--echo #
|
||||
|
||||
SET @p=_latin1'x';
|
||||
SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
|
||||
# charset convertor if @p is assigned to, no convertor otherwise
|
||||
EXPLAIN EXTENDED SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
EXPLAIN EXTENDED SELECT LENGTH(RPAD(_latin1'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p = CONVERT(UNHEX('0034002d') USING ucs2)) IS NOT NULL;
|
||||
|
||||
SET @p=_utf16'x';
|
||||
SELECT LENGTH(RPAD(_utf16'a', 766, @p)) FROM DUAL
|
||||
WHERE (@p := CONCAT(_latin1'ab', _latin1 0xD800, REPEAT(_latin1'z',1000))) IS NOT NULL;
|
||||
|
||||
SET @p= _utf8mb3'b';
|
||||
SELECT HEX(CONCAT(_utf8mb3'a', @p)) FROM DUAL
|
||||
WHERE (@p := _ucs2 0x00FF) IS NOT NULL;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -5808,8 +5808,8 @@ CREATE TABLE t (f VARCHAR(8)) CHARACTER SET utf8;
|
||||
INSERT INTO t VALUES ('foo'),('bar');
|
||||
EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f';
|
||||
GROUP_CONCAT(@x)
|
||||
0
|
||||
0
|
||||
bar
|
||||
foo
|
||||
DROP TABLE t;
|
||||
#
|
||||
# MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
|
||||
|
||||
@@ -4721,6 +4721,14 @@ bool Item_func_user_var::check_vcol_func_processor(void *arg)
|
||||
return mark_unsupported_function("@", name.str, arg, VCOL_NON_DETERMINISTIC);
|
||||
}
|
||||
|
||||
Item *Item_func_user_var::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
|
||||
{
|
||||
if (const_item())
|
||||
return Item::safe_charset_converter(thd, tocs);
|
||||
/* always convert, ignore 'conv->safe' as we don't know the charset yet */
|
||||
return new (thd->mem_root) Item_func_conv_charset(thd, this, tocs, 0);
|
||||
}
|
||||
|
||||
#define extra_size sizeof(double)
|
||||
|
||||
user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ITEM_FUNC_INCLUDED
|
||||
#define ITEM_FUNC_INCLUDED
|
||||
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB
|
||||
Copyright (c) 2009, 2026, MariaDB plc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -3552,6 +3552,7 @@ public:
|
||||
{
|
||||
return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
|
||||
}
|
||||
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user