summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/sql_string.cc6
-rw-r--r--include/m_string.h9
-rw-r--r--mysql-test/r/type_float.result12
-rw-r--r--mysql-test/t/type_float.test15
-rw-r--r--sql/sql_string.cc6
-rw-r--r--sql/unireg.h1
6 files changed, 44 insertions, 5 deletions
diff --git a/client/sql_string.cc b/client/sql_string.cc
index 17622fb7d98..c7e235522e0 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -118,7 +118,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 0e0090f52e6..e1cf7651519 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -179,6 +179,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 a3a13bb0435..f88f33b6419 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 f99dbbcea01..ea146c3938c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -130,7 +130,7 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs)
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
{
- char buff[331];
+ char buff[FLOATING_POINT_BUFFER];
uint dummy_errors;
str_charset=cs;
@@ -200,7 +200,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 d35a7715b68..2f16709e7df 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -210,7 +210,6 @@
*/
#define BIN_LOG_HEADER_SIZE 4
-#define FLOATING_POINT_BUFFER 331
#define DEFAULT_KEY_CACHE_NAME "default"