Bug#31227: memory overrun with decimal (6,6) and zerofill and group_concat

Reserve the space for the leading 0 (before the decimal point) in DECIMAL(a,a) ZEROFILL.
parent 5a1284cc
...@@ -683,6 +683,7 @@ select * from t1; ...@@ -683,6 +683,7 @@ select * from t1;
a b a b
123.12345 123.1 123.12345 123.1
drop table t1; drop table t1;
End of 4.1 tests
CREATE TABLE t1 CREATE TABLE t1
(EMPNUM CHAR(3) NOT NULL, (EMPNUM CHAR(3) NOT NULL,
HOURS DECIMAL(5)); HOURS DECIMAL(5));
...@@ -799,3 +800,10 @@ SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1; ...@@ -799,3 +800,10 @@ SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1;
ROUND(qty,3) dps ROUND(qty,dps) ROUND(qty,3) dps ROUND(qty,dps)
1.133 3 1.133 1.133 3 1.133
DROP TABLE t1; DROP TABLE t1;
create table t1 (f1 decimal(6,6),f2 decimal(6,6) zerofill);
insert into t1 values (-0.123456,0.123456);
select group_concat(f1),group_concat(f2) from t1;
group_concat(f1) group_concat(f2)
-0.123456 0.123456
drop table t1;
End of 5.0 tests
...@@ -278,7 +278,7 @@ update t1 set b=a; ...@@ -278,7 +278,7 @@ update t1 set b=a;
select * from t1; select * from t1;
drop table t1; drop table t1;
# End of 4.1 tests --echo End of 4.1 tests
# #
# Test for BUG#8397: decimal type in subselects (Item_cache_decimal) # Test for BUG#8397: decimal type in subselects (Item_cache_decimal)
...@@ -408,3 +408,14 @@ INSERT INTO t1 VALUES (1.1325,3); ...@@ -408,3 +408,14 @@ INSERT INTO t1 VALUES (1.1325,3);
SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1; SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Bug #31227: memory overrun with decimal (6,6) and zerofill and group_concat
# valgrind will complain about this (the group_concat(f2)) on unpatched mysqld.
#
create table t1 (f1 decimal(6,6),f2 decimal(6,6) zerofill);
insert into t1 values (-0.123456,0.123456);
select group_concat(f1),group_concat(f2) from t1;
drop table t1;
--echo End of 5.0 tests
...@@ -68,24 +68,43 @@ int decimal_operation_results(int result) ...@@ -68,24 +68,43 @@ int decimal_operation_results(int result)
} }
/* /**
Converting decimal to string @brief Converting decimal to string
SYNOPSIS @details Convert given my_decimal to String; allocate buffer as needed.
my_decimal2string()
@param[in] mask what problems to warn on (mask of E_DEC_* values)
return @param[in] d the decimal to print
E_DEC_OK @param[in] fixed_prec overall number of digits if ZEROFILL, 0 otherwise
E_DEC_TRUNCATED @param[in] fixed_dec number of decimal places (if fixed_prec != 0)
E_DEC_OVERFLOW @param[in] filler what char to pad with (ZEROFILL et al.)
E_DEC_OOM @param[out] *str where to store the resulting string
@return error coce
@retval E_DEC_OK
@retval E_DEC_TRUNCATED
@retval E_DEC_OVERFLOW
@retval E_DEC_OOM
*/ */
int my_decimal2string(uint mask, const my_decimal *d, int my_decimal2string(uint mask, const my_decimal *d,
uint fixed_prec, uint fixed_dec, uint fixed_prec, uint fixed_dec,
char filler, String *str) char filler, String *str)
{ {
int length= (fixed_prec ? (fixed_prec + 1) : my_decimal_string_length(d)); /*
Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
holds true iff the type is also ZEROFILL, which in turn implies
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
the user requested, plus one for a possible decimal point, plus
one if the user only wanted decimal places, but we force a leading
zero on them. Because the type is implicitly UNSIGNED, we do not
need to reserve a character for the sign. For all other cases,
fixed_prec will be 0, and my_decimal_string_length() will be called
instead to calculate the required size of the buffer.
*/
int length= (fixed_prec
? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
: my_decimal_string_length(d));
int result; int result;
if (str->alloc(length)) if (str->alloc(length))
return check_result(mask, E_DEC_OOM); return check_result(mask, E_DEC_OOM);
......
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