diff options
-rw-r--r-- | client/sql_string.cc | 6 | ||||
-rw-r--r-- | include/m_string.h | 9 | ||||
-rw-r--r-- | mysql-test/r/type_float.result | 12 | ||||
-rw-r--r-- | mysql-test/t/type_float.test | 15 | ||||
-rw-r--r-- | sql/sql_string.cc | 6 | ||||
-rw-r--r-- | sql/unireg.h | 1 |
6 files changed, 44 insertions, 5 deletions
diff --git a/client/sql_string.cc b/client/sql_string.cc index c9443f68e9c..0c89e1d0bca 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -119,7 +119,7 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) bool String::set(double num,uint decimals, CHARSET_INFO *cs) { - char buff[331]; + char buff[FLOATING_POINT_BUFFER]; uint dummy_errors; str_charset=cs; @@ -188,7 +188,9 @@ end: #else #ifdef HAVE_SNPRINTF buff[sizeof(buff)-1]=0; // Safety - snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num); + int num_chars= snprintf(buff, sizeof(buff)-1, "%.*f",(int) decimals, num); + DBUG_ASSERT(num_chars > 0); + DBUG_ASSERT(num_chars < (int) sizeof(buff)); #else sprintf(buff,"%.*f",(int) decimals,num); #endif diff --git a/include/m_string.h b/include/m_string.h index a03254ead11..94de334a050 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -216,6 +216,15 @@ extern int is_prefix(const char *, const char *); double my_strtod(const char *str, char **end, int *error); double my_atof(const char *nptr); +#ifndef NOT_FIXED_DEC +#define NOT_FIXED_DEC 31 +#endif + +/* + Max length of a floating point number. + */ +#define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC) + extern char *llstr(longlong value,char *buff); extern char *ullstr(longlong value,char *buff); #ifndef HAVE_STRTOUL diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index d3a136d53d2..c37b77b302d 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -407,4 +407,16 @@ SELECT f1 FROM t1; f1 -1.79769313486231e+308 DROP TABLE t1; +# +# Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL +# +select format(-1.7976931348623157E+307,256) as foo; +foo +ignore_float_result +select least(-1.1111111111111111111111111, +- group_concat(1.7976931348623157E+308)) as foo; +foo +ignore_float_result +select concat((truncate((-1.7976931348623157E+307),(0x1e))), +(99999999999999999999999999999999999999999999999999999999999999999)) into @a; End of 5.0 tests diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 3b7b30db6f8..95d6b6d802b 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -276,4 +276,19 @@ INSERT INTO t1 VALUES(-1.79769313486231e+308); SELECT f1 FROM t1; DROP TABLE t1; +--echo # +--echo # Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL +--echo # + +let $nine_65= +99999999999999999999999999999999999999999999999999999999999999999; + +--replace_column 1 ignore_float_result +select format(-1.7976931348623157E+307,256) as foo; +--replace_column 1 ignore_float_result +select least(-1.1111111111111111111111111, + - group_concat(1.7976931348623157E+308)) as foo; +eval select concat((truncate((-1.7976931348623157E+307),(0x1e))), + ($nine_65)) into @a; + --echo End of 5.0 tests diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 1c9a3cd7fc2..545643de49f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -117,7 +117,7 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) bool String::set(double num,uint decimals, CHARSET_INFO *cs) { - char buff[331]; + char buff[FLOATING_POINT_BUFFER]; uint dummy_errors; str_charset=cs; @@ -186,7 +186,9 @@ end: #else #ifdef HAVE_SNPRINTF buff[sizeof(buff)-1]=0; // Safety - snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num); + int num_chars= snprintf(buff, sizeof(buff)-1, "%.*f",(int) decimals, num); + DBUG_ASSERT(num_chars > 0); + DBUG_ASSERT(num_chars < (int) sizeof(buff)); #else sprintf(buff,"%.*f",(int) decimals,num); #endif diff --git a/sql/unireg.h b/sql/unireg.h index b5518809527..dd79de0781a 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -175,7 +175,6 @@ */ #define BIN_LOG_HEADER_SIZE 4 -#define FLOATING_POINT_BUFFER 331 #define DEFAULT_KEY_CACHE_NAME "default" |