Commit b8b199af authored by gshchepa/uchum@gleb.loc's avatar gshchepa/uchum@gleb.loc
Browse files

Fixed bug #31019: the MOD() function and the % operator crash the server

when a divisor is less than 1 and its fractional part is very long.
For example:
1 % .123456789123456789123456789123456789123456789123456789123456789123456789123456789;

Stack buffer overflow has been fixed in the do_div_mod function.
parent 0918fe83
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -799,3 +799,9 @@ SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1;
ROUND(qty,3)	dps	ROUND(qty,dps)
1.133	3	1.133
DROP TABLE t1;
SELECT 1 % .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS '%';
%
0.012345687012345687012345687012345687012345687012345687012345687012345687000000000
SELECT MOD(1, .123456789123456789123456789123456789123456789123456789123456789123456789123456789) AS 'MOD()';
MOD()
0.012345687012345687012345687012345687012345687012345687012345687012345687000000000
+8 −0
Original line number Diff line number Diff line
@@ -408,3 +408,11 @@ INSERT INTO t1 VALUES (1.1325,3);
SELECT ROUND(qty,3), dps, ROUND(qty,dps) FROM t1;

DROP TABLE t1;

#
# Bug#31019: MOD() function and operator crashes MySQL when
#            divisor is very long and < 1
#

SELECT 1 % .123456789123456789123456789123456789123456789123456789123456789123456789123456789 AS '%';
SELECT MOD(1, .123456789123456789123456789123456789123456789123456789123456789123456789123456789) AS 'MOD()';
+2 −1
Original line number Diff line number Diff line
@@ -2323,11 +2323,12 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2,
    }
    if (unlikely(intg0+frac0 > to->len))
    {
      stop1-=to->len-frac0-intg0;
      stop1-=frac0+intg0-to->len;
      frac0=to->len-intg0;
      to->frac=frac0*DIG_PER_DEC1;
        error=E_DEC_TRUNCATED;
    }
    DBUG_ASSERT(buf0 + (stop1 - start1) <= to->buf + to->len);
    while (start1 < stop1)
        *buf0++=*start1++;
  }