From: Tatjana Azundris Nuernberg Date: May 12 2011 3:32am Subject: bzr commit into mysql-trunk branch (tatjana.nuernberg:3366) Bug#55436 Bug#11762799 List-Archive: http://lists.mysql.com/commits/137154 X-Bug: 55436,11762799 Message-Id: <201105120332.p4C3WIsP009256@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///Users/tnurnberg/forest/11762799_/56-11762799_/ based on revid:alexander.nozdrin@stripped 3366 Tatjana Azundris Nuernberg 2011-05-12 [merge] auto-merge Bug#11762799/Bug#55436 modified: mysql-test/r/type_newdecimal.result mysql-test/t/type_newdecimal.test sql/field.cc sql/my_decimal.cc sql/my_decimal.h strings/decimal.c === modified file 'mysql-test/r/type_newdecimal.result' --- a/mysql-test/r/type_newdecimal.result 2010-09-23 12:49:56 +0000 +++ b/mysql-test/r/type_newdecimal.result 2011-05-12 03:31:08 +0000 @@ -1920,4 +1920,17 @@ SELECT SUM(DISTINCT a) FROM t1; SUM(DISTINCT a) 0.0000 DROP TABLE t1; +# +# Bug#55436: buffer overflow in debug binary of dbug_buff in +# Field_new_decimal::store_value +# +SET SQL_MODE=''; +CREATE TABLE t1(f1 DECIMAL(44,24)) ENGINE=MYISAM; +INSERT INTO t1 SET f1 = -64878E-85; +Warnings: +Note 1265 Data truncated for column 'f1' at row 1 +SELECT f1 FROM t1; +f1 +0.000000000000000000000000 +DROP TABLE IF EXISTS t1; End of 5.1 tests === modified file 'mysql-test/t/type_newdecimal.test' --- a/mysql-test/t/type_newdecimal.test 2010-09-23 12:38:24 +0000 +++ b/mysql-test/t/type_newdecimal.test 2011-05-12 03:05:12 +0000 @@ -1519,4 +1519,19 @@ SELECT AVG(DISTINCT a) FROM t1; SELECT SUM(DISTINCT a) FROM t1; DROP TABLE t1; +--echo # +--echo # Bug#55436: buffer overflow in debug binary of dbug_buff in +--echo # Field_new_decimal::store_value +--echo # + +# this threw memory warnings on Windows. Also make sure future changes +# don't change these results, as per usual. +SET SQL_MODE=''; +CREATE TABLE t1(f1 DECIMAL(44,24)) ENGINE=MYISAM; +INSERT INTO t1 SET f1 = -64878E-85; +SELECT f1 FROM t1; +DROP TABLE IF EXISTS t1; + + + --echo End of 5.1 tests === modified file 'sql/field.cc' --- a/sql/field.cc 2011-04-12 10:31:30 +0000 +++ b/sql/field.cc 2011-05-12 03:31:08 +0000 @@ -2592,7 +2592,7 @@ bool Field_new_decimal::store_value(cons DBUG_ENTER("Field_new_decimal::store_value"); #ifndef DBUG_OFF { - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value))); } #endif @@ -2607,7 +2607,7 @@ bool Field_new_decimal::store_value(cons } #ifndef DBUG_OFF { - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("info", ("saving with precision %d scale: %d value %s", (int)precision, (int)dec, dbug_decimal_as_string(dbug_buff, decimal_value))); @@ -2676,7 +2676,7 @@ int Field_new_decimal::store(const char } #ifndef DBUG_OFF - char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; + char dbug_buff[DECIMAL_MAX_STR_LENGTH+2]; DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, &decimal_value))); #endif === modified file 'sql/my_decimal.cc' --- a/sql/my_decimal.cc 2011-03-09 20:54:55 +0000 +++ b/sql/my_decimal.cc 2011-05-12 03:31:08 +0000 @@ -99,10 +99,11 @@ int my_decimal2string(uint mask, const m UNSIGNED. Hence the buffer for a ZEROFILLed value is the length the user requested, plus one for a possible decimal point, plus one if the user only wanted decimal places, but we force a leading - zero on them. Because the type is implicitly UNSIGNED, we do not - need to reserve a character for the sign. For all other cases, - fixed_prec will be 0, and my_decimal_string_length() will be called - instead to calculate the required size of the buffer. + zero on them, plus one for the '\0' terminator. Because the type + is implicitly UNSIGNED, we do not need to reserve a character for + the sign. For all other cases, fixed_prec will be 0, and + my_decimal_string_length() will be called instead to calculate the + required size of the buffer. */ int length= (fixed_prec ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1) @@ -332,7 +333,7 @@ print_decimal_buff(const my_decimal *dec const char *dbug_decimal_as_string(char *buff, const my_decimal *val) { - int length= DECIMAL_MAX_STR_LENGTH; + int length= DECIMAL_MAX_STR_LENGTH + 1; /* minimum size for buff */ if (!val) return "NULL"; (void)decimal2string((decimal_t*) val, buff, &length, 0,0,0); === modified file 'sql/my_decimal.h' --- a/sql/my_decimal.h 2011-03-18 12:25:56 +0000 +++ b/sql/my_decimal.h 2011-05-12 03:31:08 +0000 @@ -62,7 +62,7 @@ typedef struct st_mysql_time MYSQL_TIME; /** maximum length of string representation (number of maximum decimal - digits + 1 position for sign + 1 position for decimal point) + digits + 1 position for sign + 1 position for decimal point, no terminator) */ #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) @@ -243,6 +243,7 @@ inline uint32 my_decimal_precision_to_le inline int my_decimal_string_length(const my_decimal *d) { + /* length of string representation including terminating '\0' */ return decimal_string_size(d); } === modified file 'strings/decimal.c' --- a/strings/decimal.c 2011-03-03 14:25:41 +0000 +++ b/strings/decimal.c 2011-05-12 03:31:08 +0000 @@ -312,8 +312,8 @@ int decimal_actual_fraction(decimal_t *f from - value to convert to - points to buffer where string representation should be stored - *to_len - in: size of to buffer - out: length of the actually written string + *to_len - in: size of to buffer (incl. terminating '\0') + out: length of the actually written string (excl. '\0') fixed_precision - 0 if representation can be variable length and fixed_decimals will not be checked in this case. Put number as with fixed point position with this @@ -330,6 +330,7 @@ int decimal2string(const decimal_t *from int fixed_precision, int fixed_decimals, char filler) { + /* {intg_len, frac_len} output widths; {intg, frac} places in input */ int len, intg, frac= from->frac, i, intg_len, frac_len, fill; /* number digits before decimal point */ int fixed_intg= (fixed_precision ? No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).