summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.h
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2018-03-19 13:07:41 +0400
committerAlexander Barkov <bar@mariadb.com>2018-03-19 13:07:41 +0400
commitf538a64817ce583fcce558303ae9d9b6aeecf838 (patch)
treee4182297d45c0434630a14833bf0af9f8bd2d70e /sql/item_cmpfunc.h
parent31e2ab513d1d0d6caad96f613cbce3ad25c19497 (diff)
downloadmariadb-git-f538a64817ce583fcce558303ae9d9b6aeecf838.tar.gz
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).
Diffstat (limited to 'sql/item_cmpfunc.h')
-rw-r--r--sql/item_cmpfunc.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 076e6da953c..41d5ce25fd4 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1312,6 +1312,13 @@ public:
{
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)
{