summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2019-10-19 09:32:11 +0200
committerSergei Golubchik <serg@mariadb.org>2019-10-19 11:48:38 +0200
commit719ac0ad4af0dd1e20dbc94eff8f8c9f786b3393 (patch)
tree3d24a565f176fac100a0b4694c290d050780f186
parent412e3e6917233fe612354622a18b3f9cdf3a350c (diff)
downloadmariadb-git-719ac0ad4af0dd1e20dbc94eff8f8c9f786b3393.tar.gz
crash in string-to-int conversion
using a specially crafted strings one could overflow `shift` variable and cause a crash by dereferencing d10[-2147483648] (on a sufficiently old gcc). This is a correct fix and a test case for Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST
-rw-r--r--mysql-test/r/func_math.result40
-rw-r--r--mysql-test/t/func_math.test25
-rw-r--r--strings/ctype-simple.c18
3 files changed, 79 insertions, 4 deletions
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index 6edaa2e4d96..7e010297885 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -829,5 +829,45 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
+# Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST
+#
+create table t1(a int);
+insert t1 values("1e-214748364");
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+insert t1 values("1e-2147483648");
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+insert t1 values("1e-21474836480");
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+insert t1 values("1e+214748364");
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+insert t1 values("1e+2147483647");
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+insert t1 values("1e+21474836470");
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+set global max_allowed_packet= cast(2*1024*1024*1024+1024 as unsigned);
+Warnings:
+Warning 1292 Truncated incorrect max_allowed_packet value: '2147484672'
+set @a=2147483647;
+insert t1 values (concat('1', repeat('0', @a+18), 'e-', @a-1, '0'));
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1073741824) - truncated
+set global max_allowed_packet=default;
+select * from t1;
+a
+0
+0
+0
+2147483647
+2147483647
+2147483647
+NULL
+drop table t1;
+#
# End of 5.5 tests
#
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 1b5fa519c09..aca81e96de1 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -615,5 +615,30 @@ DROP TABLE t1;
--echo #
+--echo # Bug #29723340: MYSQL SERVER CRASH AFTER SQL QUERY WITH DATA ?AST
+--echo #
+
+create table t1(a int);
+insert t1 values("1e-214748364");
+insert t1 values("1e-2147483648");
+insert t1 values("1e-21474836480");
+insert t1 values("1e+214748364");
+insert t1 values("1e+2147483647");
+insert t1 values("1e+21474836470");
+
+# if max max_allowed_packet will ever be increased beyond 2GB, this could
+# break again:
+set global max_allowed_packet= cast(2*1024*1024*1024+1024 as unsigned);
+connect foo,localhost,root;
+set @a=2147483647;
+insert t1 values (concat('1', repeat('0', @a+18), 'e-', @a-1, '0'));
+disconnect foo;
+connection default;
+set global max_allowed_packet=default;
+
+select * from t1;
+drop table t1;
+
+--echo #
--echo # End of 5.5 tests
--echo #
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 5c9790966d8..ba446a7df54 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+ Copyright (c) 2009, 2019, MariaDB Corporation.
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
@@ -1524,10 +1524,20 @@ exp: /* [ E [ <sign> ] <unsigned integer> ] */
if (++str == end)
goto ret_sign;
}
- for (exponent= 0 ;
- str < end && (ch= (uchar) (*str - '0')) < 10;
- str++)
+ if (shift > 0 && !negative_exp)
+ goto ret_too_big;
+ for (exponent= 0 ; str < end && (ch= (uchar) (*str - '0')) < 10; str++)
{
+ if (negative_exp)
+ {
+ if (exponent - shift > DIGITS_IN_ULONGLONG)
+ goto ret_zero;
+ }
+ else
+ {
+ if (exponent + shift > DIGITS_IN_ULONGLONG)
+ goto ret_too_big;
+ }
exponent= exponent * 10 + ch;
}
shift+= negative_exp ? -exponent : exponent;