Commit 7bf23403 authored by Tor Didriksen's avatar Tor Didriksen

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.
parent ff2b5299
...@@ -641,3 +641,12 @@ INSERT INTO t1 (SELECT -pi()); ...@@ -641,3 +641,12 @@ INSERT INTO t1 (SELECT -pi());
Warnings: Warnings:
Warning 1265 Data truncated for column 'a' at row 1 Warning 1265 Data truncated for column 'a' at row 1
DROP TABLE t1; 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
...@@ -489,3 +489,9 @@ as foo; ...@@ -489,3 +489,9 @@ as foo;
CREATE TABLE t1(a char(0)); CREATE TABLE t1(a char(0));
INSERT INTO t1 (SELECT -pi()); INSERT INTO t1 (SELECT -pi());
DROP TABLE t1; 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')));
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -2086,7 +2086,6 @@ void Item_func_interval::fix_length_and_dec() ...@@ -2086,7 +2086,6 @@ void Item_func_interval::fix_length_and_dec()
if (dec != &range->dec) if (dec != &range->dec)
{ {
range->dec= *dec; range->dec= *dec;
range->dec.fix_buffer_pointer();
} }
} }
else else
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -1581,24 +1581,22 @@ longlong Item_func_int_div::val_int() ...@@ -1581,24 +1581,22 @@ longlong Item_func_int_div::val_int()
if (args[0]->result_type() != INT_RESULT || if (args[0]->result_type() != INT_RESULT ||
args[1]->result_type() != INT_RESULT) args[1]->result_type() != INT_RESULT)
{ {
my_decimal value0, value1, tmp; my_decimal tmp;
my_decimal *val0, *val1; my_decimal val0= *args[0]->val_decimal(&tmp);
longlong res; my_decimal val1= *args[1]->val_decimal(&tmp);
int err;
val0= args[0]->val_decimal(&value0);
val1= args[1]->val_decimal(&value1);
if ((null_value= (args[0]->null_value || args[1]->null_value))) if ((null_value= (args[0]->null_value || args[1]->null_value)))
return 0; return 0;
int err;
if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, 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) if (err == E_DEC_DIV_ZERO)
signal_divide_by_null(); signal_divide_by_null();
return 0; return 0;
} }
longlong res;
if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) & if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) &
E_DEC_OVERFLOW) E_DEC_OVERFLOW)
raise_integer_overflow(); raise_integer_overflow();
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -102,6 +102,24 @@ class my_decimal :public decimal_t ...@@ -102,6 +102,24 @@ class my_decimal :public decimal_t
public: 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() void init()
{ {
len= DECIMAL_BUFF_LENGTH; len= DECIMAL_BUFF_LENGTH;
...@@ -248,7 +266,6 @@ inline ...@@ -248,7 +266,6 @@ inline
void my_decimal2decimal(const my_decimal *from, my_decimal *to) void my_decimal2decimal(const my_decimal *from, my_decimal *to)
{ {
*to= *from; *to= *from;
to->fix_buffer_pointer();
} }
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -521,9 +521,6 @@ void field_decimal::add() ...@@ -521,9 +521,6 @@ void field_decimal::add()
{ {
found = 1; found = 1;
min_arg = max_arg = sum[0] = *dec; 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); my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec);
cur_sum= 0; cur_sum= 0;
min_length = max_length = length; min_length = max_length = length;
...@@ -545,12 +542,10 @@ void field_decimal::add() ...@@ -545,12 +542,10 @@ void field_decimal::add()
if (my_decimal_cmp(dec, &min_arg) < 0) if (my_decimal_cmp(dec, &min_arg) < 0)
{ {
min_arg= *dec; min_arg= *dec;
min_arg.fix_buffer_pointer();
} }
if (my_decimal_cmp(dec, &max_arg) > 0) if (my_decimal_cmp(dec, &max_arg) > 0)
{ {
max_arg= *dec; max_arg= *dec;
max_arg.fix_buffer_pointer();
} }
} }
} }
......
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 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 NOTE: this library implements SQL standard "exact numeric" type
......
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