Commit ded8fa56 authored by serg@serg.mylan's avatar serg@serg.mylan

my_strtod fixes:

sigsegv protection (exp overflow)
don't return inf!
use errno=EOVERFLOW to signal an overflow (as my_strntod uses errno anyway)
if errno will be too slow, my_strtod can be changed to return overflow status in a parameter (like my_strntod does)
parent 42c19ada
...@@ -218,6 +218,9 @@ extern int is_prefix(const char *, const char *); ...@@ -218,6 +218,9 @@ extern int is_prefix(const char *, const char *);
/* Conversion routines */ /* Conversion routines */
double my_strtod(const char *str, char **end); double my_strtod(const char *str, char **end);
double my_atof(const char *nptr); double my_atof(const char *nptr);
#ifndef EOVERFLOW
#define EOVERFLOW 84
#endif
#ifdef USE_MY_ITOA #ifdef USE_MY_ITOA
extern char *my_itoa(int val,char *dst,int radix); extern char *my_itoa(int val,char *dst,int radix);
......
...@@ -169,7 +169,6 @@ set @value= "1e+1111111111a"; ...@@ -169,7 +169,6 @@ set @value= "1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings: Warnings:
Warning 1265 Data truncated for column 'f_double ' at row 1 Warning 1265 Data truncated for column 'f_double ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double ' at row 1
Warning 1265 Data truncated for column 'f_float ' at row 1 Warning 1265 Data truncated for column 'f_float ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float ' at row 1
Warning 1265 Data truncated for column 'f_double_7_2 ' at row 1 Warning 1265 Data truncated for column 'f_double_7_2 ' at row 1
...@@ -177,7 +176,6 @@ Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1 ...@@ -177,7 +176,6 @@ Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1
Warning 1265 Data truncated for column 'f_float_4_3 ' at row 1 Warning 1265 Data truncated for column 'f_float_4_3 ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1
Warning 1265 Data truncated for column 'f_double_u ' at row 1 Warning 1265 Data truncated for column 'f_double_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double_u ' at row 1
Warning 1265 Data truncated for column 'f_float_u ' at row 1 Warning 1265 Data truncated for column 'f_float_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_u ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_u ' at row 1
Warning 1265 Data truncated for column 'f_double_15_1_u ' at row 1 Warning 1265 Data truncated for column 'f_double_15_1_u ' at row 1
...@@ -199,7 +197,6 @@ set @value= "-1e+1111111111a"; ...@@ -199,7 +197,6 @@ set @value= "-1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings: Warnings:
Warning 1265 Data truncated for column 'f_double ' at row 1 Warning 1265 Data truncated for column 'f_double ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double ' at row 1
Warning 1265 Data truncated for column 'f_float ' at row 1 Warning 1265 Data truncated for column 'f_float ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float ' at row 1
Warning 1265 Data truncated for column 'f_double_7_2 ' at row 1 Warning 1265 Data truncated for column 'f_double_7_2 ' at row 1
...@@ -228,17 +225,15 @@ f_float_3_1_u 0.0 ...@@ -228,17 +225,15 @@ f_float_3_1_u 0.0
set @value= 1e+1111111111; set @value= 1e+1111111111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings: Warnings:
Warning 1264 Data truncated, out of range for column 'f_double ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1 Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_u ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double_15_1_u ' at row 1 Warning 1264 Data truncated, out of range for column 'f_double_15_1_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_3_1_u ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_3_1_u ' at row 1
select * from t1 where `number `=last_insert_id(); select * from t1 where `number `=last_insert_id();
number 6 number 6
original_value inf original_value 1.7976931348623e+308
f_double 1.79769313486232e+308 f_double 1.79769313486232e+308
f_float 3.40282e+38 f_float 3.40282e+38
f_double_7_2 99999.99 f_double_7_2 99999.99
...@@ -250,7 +245,6 @@ f_float_3_1_u 99.9 ...@@ -250,7 +245,6 @@ f_float_3_1_u 99.9
set @value= -1e+1111111111; set @value= -1e+1111111111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
Warnings: Warnings:
Warning 1264 Data truncated, out of range for column 'f_double ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float ' at row 1
Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1 Warning 1264 Data truncated, out of range for column 'f_double_7_2 ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_4_3 ' at row 1
...@@ -260,7 +254,7 @@ Warning 1264 Data truncated, out of range for column 'f_double_15_1_u ' at row 1 ...@@ -260,7 +254,7 @@ Warning 1264 Data truncated, out of range for column 'f_double_15_1_u ' at row 1
Warning 1264 Data truncated, out of range for column 'f_float_3_1_u ' at row 1 Warning 1264 Data truncated, out of range for column 'f_float_3_1_u ' at row 1
select * from t1 where `number `=last_insert_id(); select * from t1 where `number `=last_insert_id();
number 7 number 7
original_value -inf original_value -1.7976931348623e+308
f_double -1.79769313486232e+308 f_double -1.79769313486232e+308
f_float -3.40282e+38 f_float -3.40282e+38
f_double_7_2 -99999.99 f_double_7_2 -99999.99
......
...@@ -46,8 +46,6 @@ UNLOCK TABLES; ...@@ -46,8 +46,6 @@ UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a double); CREATE TABLE t1 (a double);
INSERT INTO t1 VALUES (-9e999999); INSERT INTO t1 VALUES (-9e999999);
Warnings:
Warning 1264 Data truncated, out of range for column 'a' at row 1
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
An alternative implementation of "strtod()" that is both An alternative implementation of "strtod()" that is both
simplier, and thread-safe. simplier, and thread-safe.
From mit-threads as bundled with MySQL 3.22 From mit-threads as bundled with MySQL 3.23
SQL:2003 specifies a number as SQL:2003 specifies a number as
...@@ -41,6 +41,7 @@ double my_strtod(const char *str, char **end) ...@@ -41,6 +41,7 @@ double my_strtod(const char *str, char **end)
double result= 0.0; double result= 0.0;
int negative, ndigits; int negative, ndigits;
const char *old_str; const char *old_str;
my_bool overflow=0;
while (my_isspace(&my_charset_latin1, *str)) while (my_isspace(&my_charset_latin1, *str))
str++; str++;
...@@ -85,6 +86,7 @@ double my_strtod(const char *str, char **end) ...@@ -85,6 +86,7 @@ double my_strtod(const char *str, char **end)
double scaler= 1.0; double scaler= 1.0;
while (my_isdigit (&my_charset_latin1, *str)) while (my_isdigit (&my_charset_latin1, *str))
{ {
if (exp < 9999) /* protection against exp overflow */
exp= exp*10 + *str - '0'; exp= exp*10 + *str - '0';
str++; str++;
} }
...@@ -93,7 +95,7 @@ double my_strtod(const char *str, char **end) ...@@ -93,7 +95,7 @@ double my_strtod(const char *str, char **end)
if (neg) if (neg)
result= 0.0; result= 0.0;
else else
result= DBL_MAX*10; overflow=1;
goto done; goto done;
} }
while (exp >= 100) while (exp >= 100)
...@@ -113,6 +115,12 @@ done: ...@@ -113,6 +115,12 @@ done:
if (end) if (end)
*end = (char *)str; *end = (char *)str;
if (overflow || ((overflow=isinf(result))))
{
result=DBL_MAX;
errno=EOVERFLOW;
}
return negative ? -result : result; return negative ? -result : result;
} }
......
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