summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgkodinov@mysql.com <>2006-07-06 13:18:05 +0300
committergkodinov@mysql.com <>2006-07-06 13:18:05 +0300
commit732b175c296ee6e858d181b5b2bf4cfc19f18598 (patch)
tree2e3ef4ddaedcb26307cc9412256ab6f787169763
parent3cc6d95d18a6a94f1f6d920b5fb5f11564cf92b9 (diff)
downloadmariadb-git-732b175c296ee6e858d181b5b2bf4cfc19f18598.tar.gz
Bug #20569 Garbage in DECIMAL results from some mathematical functions
Adding decimal "digits" in multiplication resulted in signed overflow and producing wrong results. Fixed by using large enough buffers and intermediary result types : dec2 (currently longlong) to hold result of adding decimal "digits" (currently int32).
-rw-r--r--mysql-test/r/select.result3
-rw-r--r--mysql-test/t/select.test5
-rw-r--r--strings/decimal.c13
3 files changed, 18 insertions, 3 deletions
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index e6c590489a0..7f01d453906 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3395,3 +3395,6 @@ a t1.b + 0 t1.c + 0 a t2.b + 0 c d
1 0 1 1 0 1 NULL
2 0 1 NULL NULL NULL NULL
drop table t1,t2;
+SELECT 0.9888889889 * 1.011111411911;
+0.9888889889 * 1.011111411911
+0.9998769417899202067879
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index b75d0dd8bb6..b44f682c02e 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2901,3 +2901,8 @@ from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
where t1.b <> 1 order by t1.a;
drop table t1,t2;
+
+#
+# Bug #20569: Garbage in DECIMAL results from some mathematical functions
+#
+SELECT 0.9888889889 * 1.011111411911;
diff --git a/strings/decimal.c b/strings/decimal.c
index 8786a513945..ecd92a54cc9 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -170,6 +170,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={
#define ADD(to, from1, from2, carry) /* assume carry <= 1 */ \
do \
{ \
+ DBUG_ASSERT((carry) <= 1); \
dec1 a=(from1)+(from2)+(carry); \
if (((carry)= a >= DIG_BASE)) /* no division here! */ \
a-=DIG_BASE; \
@@ -179,7 +180,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={
#define ADD2(to, from1, from2, carry) \
do \
{ \
- dec1 a=(from1)+(from2)+(carry); \
+ dec2 a=((dec2)(from1))+(from2)+(carry); \
if (((carry)= a >= DIG_BASE)) \
a-=DIG_BASE; \
if (unlikely(a >= DIG_BASE)) \
@@ -187,7 +188,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={
a-=DIG_BASE; \
carry++; \
} \
- (to)=a; \
+ (to)=(dec1) a; \
} while(0)
#define SUB(to, from1, from2, carry) /* to=from1-from2 */ \
@@ -1998,7 +1999,13 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
ADD2(*buf0, *buf0, lo, carry);
carry+=hi;
}
- for (; carry; buf0--)
+ if (carry)
+ {
+ if (buf0 < to->buf)
+ return E_DEC_OVERFLOW;
+ ADD2(*buf0, *buf0, 0, carry);
+ }
+ for (buf0--; carry; buf0--)
{
if (buf0 < to->buf)
return E_DEC_OVERFLOW;