summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Glukhov <sergey.glukhov@oracle.com>2010-12-21 14:34:11 +0300
committerSergey Glukhov <sergey.glukhov@oracle.com>2010-12-21 14:34:11 +0300
commite2db8e6ccb2655ec5706305b491540ad3f1c8267 (patch)
treef5ef5d20bde3490e4a43f28f7b52f2cd24952564
parentd5bf6b8aa8bb1c745abeb5e245f0398858ca1461 (diff)
downloadmariadb-git-e2db8e6ccb2655ec5706305b491540ad3f1c8267.tar.gz
Bug#58030 crash in Item_func_geometry_from_text::val_str
Item_sum_max/Item_sum_min incorrectly set null_value flag and attempt to get result in parent functions leads to crash. This happens due to double evaluation of the function argumet. First evaluation happens in the comparator and second one happens in Item_cache::cache_value(). The fix is to introduce new Item_cache object which holds result of the argument and use this cached value as an argument of the comparator. mysql-test/r/func_group.result: test case mysql-test/t/func_group.test: test case sql/item.cc: added assertion that ether we have some result or result is NULL. sql/item_sum.cc: introduce new Item_cache object which holds result of the argument and use this cached value as an argument of the comparator. sql/item_sum.h: introduce new Item_cache object which holds result of the argument and use this cached value as an argument of the comparator.
-rw-r--r--mysql-test/r/func_group.result12
-rw-r--r--mysql-test/t/func_group.test20
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item_sum.cc20
-rw-r--r--sql/item_sum.h10
5 files changed, 52 insertions, 14 deletions
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 606f879b47f..60c00c49b33 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1724,4 +1724,16 @@ m
1
DROP TABLE t1;
#
+# Bug#58030 crash in Item_func_geometry_from_text::val_str
+#
+SELECT MAX(TIMESTAMP(RAND(0)));
+SELECT MIN(TIMESTAMP(RAND(0)));
+#
+# Bug#58177 crash and valgrind warnings in decimal and protocol sending functions...
+#
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+#
End of 5.1 tests
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 72a78f612a2..338bf0e7718 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -1097,5 +1097,25 @@ SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1
DROP TABLE t1;
--echo #
+--echo # Bug#58030 crash in Item_func_geometry_from_text::val_str
+--echo #
+
+--disable_result_log
+
+SELECT MAX(TIMESTAMP(RAND(0)));
+SELECT MIN(TIMESTAMP(RAND(0)));
+
+--echo #
+--echo # Bug#58177 crash and valgrind warnings in decimal and protocol sending functions...
+--echo #
+
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
+
+--enable_result_log
+
+--echo #
--echo End of 5.1 tests
diff --git a/sql/item.cc b/sql/item.cc
index c75db2dc15b..c01671aff56 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5572,6 +5572,10 @@ bool Item::send(Protocol *protocol, String *buffer)
String *res;
if ((res=val_str(buffer)))
result= protocol->store(res->ptr(),res->length(),res->charset());
+ else
+ {
+ DBUG_ASSERT(null_value);
+ }
break;
}
case MYSQL_TYPE_TINY:
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index a60a6b3ef95..5493020b67b 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -666,8 +666,10 @@ void Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg)
value= Item_cache::get_cache(item);
value->setup(item);
value->store(value_arg);
+ arg_cache= Item_cache::get_cache(item);
+ arg_cache->setup(item);
cmp= new Arg_comparator();
- cmp->set_cmp_func(this, args, (Item**)&value, FALSE);
+ cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE);
collation.set(item->collation);
}
@@ -1639,11 +1641,11 @@ Item *Item_sum_min::copy_or_same(THD* thd)
bool Item_sum_min::add()
{
/* args[0] < value */
- int res= cmp->compare();
- if (!args[0]->null_value &&
- (null_value || res < 0))
+ arg_cache->cache_value();
+ if (!arg_cache->null_value &&
+ (null_value || cmp->compare() < 0))
{
- value->store(args[0]);
+ value->store(arg_cache);
value->cache_value();
null_value= 0;
}
@@ -1662,11 +1664,11 @@ Item *Item_sum_max::copy_or_same(THD* thd)
bool Item_sum_max::add()
{
/* args[0] > value */
- int res= cmp->compare();
- if (!args[0]->null_value &&
- (null_value || res > 0))
+ arg_cache->cache_value();
+ if (!arg_cache->null_value &&
+ (null_value || cmp->compare() > 0))
{
- value->store(args[0]);
+ value->store(arg_cache);
value->cache_value();
null_value= 0;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 26290a812f4..de988c196ec 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -823,7 +823,7 @@ class Item_cache;
class Item_sum_hybrid :public Item_sum
{
protected:
- Item_cache *value;
+ Item_cache *value, *arg_cache;
Arg_comparator *cmp;
Item_result hybrid_type;
enum_field_types hybrid_field_type;
@@ -832,14 +832,14 @@ protected:
public:
Item_sum_hybrid(Item *item_par,int sign)
- :Item_sum(item_par), value(0), cmp(0),
+ :Item_sum(item_par), value(0), arg_cache(0), cmp(0),
hybrid_type(INT_RESULT), hybrid_field_type(MYSQL_TYPE_LONGLONG),
cmp_sign(sign), was_values(TRUE)
{ collation.set(&my_charset_bin); }
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
- :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type),
- hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign),
- was_values(item->was_values)
+ :Item_sum(thd, item), value(item->value), arg_cache(0),
+ hybrid_type(item->hybrid_type), hybrid_field_type(item->hybrid_field_type),
+ cmp_sign(item->cmp_sign), was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
void setup_hybrid(Item *item, Item *value_arg);