Commit f538a648 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple

cmp_item_sort_string::store_value() did not cache the string returned
from item->val_str(), whose result can point to various private members
such as Item_char_typecast::tmp_value.

- cmp_item_sort_string::store_value() remembered the pointer returned
  from item->val_str() poiting to tmp_value into cmp_item_string::value_res.
- Later, cmp_item_real::store_value() was called, which called
  Item_str_func::val_real(), which called Item_char_typecast::val_str(&tmp)
  using a local stack variable "String tmp". Item_char_typecast::tmp_value
  was overwritten and become a link to "tmp":
  tmp_value.Ptr freed its own buffer and set to point to the buffer
  owned by "tmp".
- On return from Item_str_func::val_real(), "String tmp" was destructed,
  but "tmp_value" still pointed to the buffer owned by "tmp",
  So tmp_value.Ptr became invalid.
- Then cmp_item_sort_string() passed cmp_item_string::value_res to sortcmp().
  At this point, value_res still pointed to an invalid value of
  Item_char_typecast::tmp_value.

Fix:
changing cmp_item_sort_string::store_value() to force copying
to cmp_item_string::value if item->val_str(&value) returned
a different pointer (instead of &value).
parent 31e2ab51
......@@ -8208,5 +8208,18 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d` from `test`.`t1` where ((coalesce(`test`.`t1`.`c`,0) = '3 ') and (coalesce(`test`.`t1`.`d`,0) = '3 '))
DROP TABLE t1;
#
# MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple
#
SET NAMES latin1;
SELECT CONVERT(1, CHAR) IN ('100', 10, '101');
CONVERT(1, CHAR) IN ('100', 10, '101')
0
SELECT CONVERT(1, CHAR) IN ('100', 10, '1');
CONVERT(1, CHAR) IN ('100', 10, '1')
1
SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
CONVERT(1, CHAR) IN ('100', '10', '1')
1
#
# End of 10.1 tests
#
......@@ -10535,5 +10535,18 @@ CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1)
Warnings:
Warning 1977 Cannot convert 'utf8' character 0xC499 to 'latin1'
#
# MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple
#
SET NAMES utf8;
SELECT CONVERT(1, CHAR) IN ('100', 10, '101');
CONVERT(1, CHAR) IN ('100', 10, '101')
0
SELECT CONVERT(1, CHAR) IN ('100', 10, '1');
CONVERT(1, CHAR) IN ('100', 10, '1')
1
SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
CONVERT(1, CHAR) IN ('100', '10', '1')
1
#
# End of 10.1 tests
#
......@@ -389,6 +389,15 @@ EXPLAIN EXTENDED
SELECT * FROM t1 WHERE COALESCE(c,0)='3 ' AND COALESCE(d,0)=COALESCE(c,0);
DROP TABLE t1;
--echo #
--echo # MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple
--echo #
SET NAMES latin1;
SELECT CONVERT(1, CHAR) IN ('100', 10, '101');
SELECT CONVERT(1, CHAR) IN ('100', 10, '1');
SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
--echo #
--echo # End of 10.1 tests
--echo #
......@@ -2024,6 +2024,16 @@ SELECT CONVERT(_utf8 0xC499 USING latin1);
SELECT CAST(_utf8 0xC499 AS CHAR CHARACTER SET latin1);
--echo #
--echo # MDEV-15005 ASAN: stack-buffer-overflow in my_strnncollsp_simple
--echo #
SET NAMES utf8;
SELECT CONVERT(1, CHAR) IN ('100', 10, '101');
SELECT CONVERT(1, CHAR) IN ('100', 10, '1');
SELECT CONVERT(1, CHAR) IN ('100', '10', '1');
--echo #
--echo # End of 10.1 tests
--echo #
......@@ -1312,6 +1312,13 @@ class cmp_item_sort_string :public cmp_item_string
{
value_res= item->val_str(&value);
m_null_value= item->null_value;
// Make sure to cache the result String inside "value"
if (value_res && value_res != &value)
{
if (value.copy(*value_res))
value.set("", 0, item->collation.collation);
value_res= &value;
}
}
int cmp(Item *arg)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment