Skip to content

Commit b777b74

Browse files
committed
MDEV-28345 ASAN: use-after-poison or unknown-crash in my_strtod_int from charset_info_st::strntod or test_if_number
This patch fixes two problems: - The code inside my_strtod_int() in strings/dtoa.c could test the byte behind the end of the string when processing the mantissa. Rewriting the code to avoid this. - The code in test_if_number() in sql/sql_analyse.cc called my_atof() which is unsafe and makes the called my_strtod_int() look behind the end of the string if the input string is not 0-terminated. Fixing test_if_number() to use my_strtod() instead, passing the correct end pointer.
1 parent 383d53e commit b777b74

File tree

6 files changed

+94
-10
lines changed

6 files changed

+94
-10
lines changed

mysql-test/main/func_analyse.result

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,22 @@ DROP TABLE t1;
222222
#
223223
# End of 10.4 tests
224224
#
225+
#
226+
# Start of 10.5 tests
227+
#
228+
#
229+
# MDEV-28345 ASAN: use-after-poison or unknown-crash in my_strtod_int from charset_info_st::strntod or test_if_number
230+
#
231+
SET sql_mode='';
232+
CREATE TABLE t1 (c CHAR(10) KEY);
233+
INSERT INTO t1 VALUES (1.755555555);
234+
Warnings:
235+
Warning 1265 Data truncated for column 'c' at row 1
236+
SELECT * FROM t1 PROCEDURE ANALYSE();
237+
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
238+
test.t1.c 1.75555555 1.75555555 10 10 0 0 10.0000 NULL ENUM('1.75555555') NOT NULL
239+
DROP TABLE t1;
240+
SET sql_mode=DEFAULT;
241+
#
242+
# End of 10.5 tests
243+
#

mysql-test/main/func_analyse.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,23 @@ DROP TABLE t1;
230230
--echo #
231231
--echo # End of 10.4 tests
232232
--echo #
233+
234+
235+
--echo #
236+
--echo # Start of 10.5 tests
237+
--echo #
238+
239+
--echo #
240+
--echo # MDEV-28345 ASAN: use-after-poison or unknown-crash in my_strtod_int from charset_info_st::strntod or test_if_number
241+
--echo #
242+
243+
SET sql_mode='';
244+
CREATE TABLE t1 (c CHAR(10) KEY);
245+
INSERT INTO t1 VALUES (1.755555555);
246+
SELECT * FROM t1 PROCEDURE ANALYSE();
247+
DROP TABLE t1;
248+
SET sql_mode=DEFAULT;
249+
250+
--echo #
251+
--echo # End of 10.5 tests
252+
--echo #

mysql-test/main/type_num_innodb.result

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,27 @@ DROP TABLE t1,t2;
8888
#
8989
# End of 10.2 tests
9090
#
91+
#
92+
# Start of 10.5 tests
93+
#
94+
#
95+
# MDEV-28345 ASAN: use-after-poison or unknown-crash in my_strtod_int from charset_info_st::strntod or test_if_number
96+
#
97+
CREATE TABLE t1 (c BLOB) ENGINE=InnoDB;
98+
INSERT INTO t1 VALUES ('0.0e'),('0.0e+0');
99+
SELECT * FROM t1 WHERE COALESCE(c)=0.0;
100+
c
101+
0.0e
102+
0.0e+0
103+
Warnings:
104+
Warning 1292 Truncated incorrect DOUBLE value: '0.0e'
105+
SELECT * FROM t1 WHERE COALESCE(c)=0.0e0;
106+
c
107+
0.0e
108+
0.0e+0
109+
Warnings:
110+
Warning 1292 Truncated incorrect DOUBLE value: '0.0e'
111+
DROP TABLE t1;
112+
#
113+
# End of 10.5 tests
114+
#

mysql-test/main/type_num_innodb.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,22 @@ DROP TABLE t1,t2;
3939
--echo #
4040
--echo # End of 10.2 tests
4141
--echo #
42+
43+
44+
--echo #
45+
--echo # Start of 10.5 tests
46+
--echo #
47+
48+
--echo #
49+
--echo # MDEV-28345 ASAN: use-after-poison or unknown-crash in my_strtod_int from charset_info_st::strntod or test_if_number
50+
--echo #
51+
52+
CREATE TABLE t1 (c BLOB) ENGINE=InnoDB;
53+
INSERT INTO t1 VALUES ('0.0e'),('0.0e+0');
54+
SELECT * FROM t1 WHERE COALESCE(c)=0.0;
55+
SELECT * FROM t1 WHERE COALESCE(c)=0.0e0;
56+
DROP TABLE t1;
57+
58+
--echo #
59+
--echo # End of 10.5 tests
60+
--echo #

sql/sql_analyse.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
258258
info->decimals++;
259259
if (str == end)
260260
{
261-
info->dval = my_atof(begin);
261+
int error;
262+
const char *end2= end;
263+
info->dval= my_strtod(begin, (char **) &end2, &error);
262264
DBUG_RETURN(1);
263265
}
264266
}

strings/dtoa.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,22 +1465,22 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
14651465
s00= s;
14661466
esign= 0;
14671467
if (++s < end)
1468-
switch (c= *s) {
1468+
switch (*s) {
14691469
case '-': esign= 1;
14701470
/* fall through */
1471-
case '+': c= *++s;
1471+
case '+': s++;
14721472
}
1473-
if (s < end && c >= '0' && c <= '9')
1473+
if (s < end && *s >= '0' && *s <= '9')
14741474
{
1475-
while (s < end && c == '0')
1476-
c= *++s;
1477-
if (s < end && c > '0' && c <= '9') {
1478-
L= c - '0';
1475+
while (s < end && *s == '0')
1476+
s++;
1477+
if (s < end && *s > '0' && *s <= '9') {
1478+
L= *s - '0';
14791479
s1= s;
1480-
while (++s < end && (c= *s) >= '0' && c <= '9')
1480+
while (++s < end && *s >= '0' && *s <= '9')
14811481
{
14821482
if (L < 19999)
1483-
L= 10*L + c - '0';
1483+
L= 10*L + *s - '0';
14841484
}
14851485
if (s - s1 > 8 || L > 19999)
14861486
/* Avoid confusion from exponents

0 commit comments

Comments
 (0)