From: Tor Didriksen Date: January 14 2011 9:30am Subject: bzr push into mysql-5.5 branch (tor.didriksen:3241 to 3242) Bug#59241 List-Archive: http://lists.mysql.com/commits/128705 X-Bug: 59241 Message-Id: <20110114093053.304073776@atum07.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3242 Tor Didriksen 2011-01-14 Bug #59241 invalid memory read in do_div_mod with doubly assigned variables Fix: copy my_decimal by value, to avoid dangling pointers. @ mysql-test/r/func_math.result New test case. @ mysql-test/t/func_math.test New test case. @ sql/item_cmpfunc.cc No need to call fix_buffer_pointer() anymore. @ sql/item_func.cc Copy my_decimal by value, to avoid dangling pointers. @ sql/my_decimal.h Implement proper copy constructor and assignment operator for my_decimal. @ sql/sql_analyse.cc No need to call fix_buffer_pointer() anymore. @ strings/decimal.c Remove #line directive: it messes up TAGS and it confuses gdb when debugging. modified: mysql-test/r/func_math.result mysql-test/t/func_math.test sql/item_cmpfunc.cc sql/item_func.cc sql/my_decimal.h sql/sql_analyse.cc strings/decimal.c 3241 Serge Kozlov 2011-01-14 Bug#54820: master_connect_retry increased for Valgrind environment support Bug#58525: separate string and numbers for comparing modified: mysql-test/include/wait_for_status_var.inc mysql-test/suite/rpl/r/rpl_heartbeat_basic.result mysql-test/suite/rpl/t/rpl_heartbeat_basic.test === modified file 'mysql-test/r/func_math.result' --- a/mysql-test/r/func_math.result 2010-12-24 11:21:44 +0000 +++ b/mysql-test/r/func_math.result 2011-01-14 09:05:14 +0000 @@ -641,3 +641,12 @@ INSERT INTO t1 (SELECT -pi()); Warnings: Warning 1265 Data truncated for column 'a' at row 1 DROP TABLE t1; +# +# Bug #59241 invalid memory read +# in do_div_mod with doubly assigned variables +# +SELECT ((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))); +((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))) +NULL +Warnings: +Warning 1366 Incorrect decimal value: '' for column '' at row -1 === modified file 'mysql-test/t/func_math.test' --- a/mysql-test/t/func_math.test 2010-12-24 11:21:44 +0000 +++ b/mysql-test/t/func_math.test 2011-01-14 09:05:14 +0000 @@ -489,3 +489,9 @@ as foo; CREATE TABLE t1(a char(0)); INSERT INTO t1 (SELECT -pi()); DROP TABLE t1; + +--echo # +--echo # Bug #59241 invalid memory read +--echo # in do_div_mod with doubly assigned variables +--echo # +SELECT ((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))); === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-01-13 08:33:30 +0000 +++ b/sql/item_cmpfunc.cc 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -2086,7 +2086,6 @@ void Item_func_interval::fix_length_and_ if (dec != &range->dec) { range->dec= *dec; - range->dec.fix_buffer_pointer(); } } else === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2010-12-29 00:26:31 +0000 +++ b/sql/item_func.cc 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -1581,24 +1581,22 @@ longlong Item_func_int_div::val_int() if (args[0]->result_type() != INT_RESULT || args[1]->result_type() != INT_RESULT) { - my_decimal value0, value1, tmp; - my_decimal *val0, *val1; - longlong res; - int err; - - val0= args[0]->val_decimal(&value0); - val1= args[1]->val_decimal(&value1); + my_decimal tmp; + my_decimal val0= *args[0]->val_decimal(&tmp); + my_decimal val1= *args[1]->val_decimal(&tmp); if ((null_value= (args[0]->null_value || args[1]->null_value))) return 0; + int err; if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, - val0, val1, 0)) > 3) + &val0, &val1, 0)) > 3) { if (err == E_DEC_DIV_ZERO) signal_divide_by_null(); return 0; } + longlong res; if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) & E_DEC_OVERFLOW) raise_integer_overflow(); === modified file 'sql/my_decimal.h' --- a/sql/my_decimal.h 2010-10-19 22:51:34 +0000 +++ b/sql/my_decimal.h 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2006 MySQL AB +/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -102,6 +102,24 @@ class my_decimal :public decimal_t public: + my_decimal(const my_decimal &rhs) : decimal_t(rhs) + { + for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) + buffer[i]= rhs.buffer[i]; + fix_buffer_pointer(); + } + + my_decimal& operator=(const my_decimal &rhs) + { + if (this == &rhs) + return *this; + decimal_t::operator=(rhs); + for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) + buffer[i]= rhs.buffer[i]; + fix_buffer_pointer(); + return *this; + } + void init() { len= DECIMAL_BUFF_LENGTH; @@ -248,7 +266,6 @@ inline void my_decimal2decimal(const my_decimal *from, my_decimal *to) { *to= *from; - to->fix_buffer_pointer(); } === modified file 'sql/sql_analyse.cc' --- a/sql/sql_analyse.cc 2010-07-09 12:28:51 +0000 +++ b/sql/sql_analyse.cc 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -521,9 +521,6 @@ void field_decimal::add() { found = 1; min_arg = max_arg = sum[0] = *dec; - min_arg.fix_buffer_pointer(); - max_arg.fix_buffer_pointer(); - sum[0].fix_buffer_pointer(); my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec); cur_sum= 0; min_length = max_length = length; @@ -545,12 +542,10 @@ void field_decimal::add() if (my_decimal_cmp(dec, &min_arg) < 0) { min_arg= *dec; - min_arg.fix_buffer_pointer(); } if (my_decimal_cmp(dec, &max_arg) > 0) { max_arg= *dec; - max_arg.fix_buffer_pointer(); } } } === modified file 'strings/decimal.c' --- a/strings/decimal.c 2010-07-20 19:30:10 +0000 +++ b/strings/decimal.c 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#line 18 "decimal.c" - /* ======================================================================= NOTE: this library implements SQL standard "exact numeric" type No bundle (reason: useless for push emails).