List:Commits« Previous MessageNext Message »
From:Tatiana Azundris Nurnberg Date:May 5 2011 10:53am
Subject:bzr push into mysql-trunk branch (azundris:3365 to 3367) Bug#11762799
View as plain text  
 3367 Tatiana Azundris Nurnberg	2011-05-05
      Bug#11762799: buffer overflow in debug binary of dbug_buff in Field_new_decimal::store_value
      
      extra, more aggressive fixes for 5.6+

    modified:
      sql/log_event.cc
      sql/my_decimal.cc
      sql/protocol.cc
      sql/sql_analyse.cc
      strings/decimal.c
 3366 Tatiana Azundris Nurnberg	2011-05-05 [merge]
      auto-merge

    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
 3365 Alexander Nozdrin	2011-05-04 [merge]
      Auto-merge patches for Bug#27480 from mysql-trunk-bug27480.

    added:
      mysql-test/collections/mysql-trunk-bug27480.push
    modified:
      mysql-test/include/handler.inc
      mysql-test/r/alter_table.result
      mysql-test/r/flush_read_lock.result
      mysql-test/r/grant2.result
      mysql-test/r/grant4.result
      mysql-test/r/handler_innodb.result
      mysql-test/r/handler_myisam.result
      mysql-test/r/merge.result
      mysql-test/r/ps_ddl.result
      mysql-test/r/temp_table.result
      mysql-test/suite/innodb/r/innodb_mysql.result
      mysql-test/suite/innodb/t/innodb_mysql.test
      mysql-test/suite/rpl/r/rpl_create_if_not_exists.result
      mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
      mysql-test/t/alter_table.test
      mysql-test/t/flush_read_lock.test
      mysql-test/t/grant2.test
      mysql-test/t/grant4.test
      mysql-test/t/handler_myisam.test
      mysql-test/t/merge.test
      mysql-test/t/ps_ddl.test
      mysql-test/t/temp_table.test
      sql/log_event.cc
      sql/sp_head.cc
      sql/sql_acl.cc
      sql/sql_acl.h
      sql/sql_admin.cc
      sql/sql_alter.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_class.h
      sql/sql_db.cc
      sql/sql_handler.cc
      sql/sql_handler.h
      sql/sql_insert.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_parse.h
      sql/sql_partition_admin.cc
      sql/sql_prepare.cc
      sql/sql_rename.cc
      sql/sql_show.cc
      sql/sql_table.cc
      sql/sql_truncate.cc
      sql/sql_view.cc
      sql/sql_yacc.yy
      sql/table.cc
      sql/table.h
      storage/myisammrg/ha_myisammrg.cc
=== 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-05 06:55:53 +0000
@@ -1909,6 +1909,19 @@ mult	v_net_with_discount	v_total
 1.0000	27.18	27.180000
 DROP TABLE currencies, payments, sub_tasks;
 #
+# 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;
+#
 # BUG#52171: distinct aggregates on unsigned decimal fields trigger assertions
 #
 CREATE TABLE t1 (a DECIMAL(4,4) UNSIGNED);

=== 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-05 06:40:33 +0000
@@ -1510,6 +1510,19 @@ group by PAY.id + 1;
 DROP TABLE currencies, payments, sub_tasks;
 
 --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 #
 --echo # BUG#52171: distinct aggregates on unsigned decimal fields trigger assertions
 --echo #
 

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2011-04-12 10:31:30 +0000
+++ b/sql/field.cc	2011-05-05 06:55:53 +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/log_event.cc'
--- a/sql/log_event.cc	2011-05-04 07:51:15 +0000
+++ b/sql/log_event.cc	2011-05-05 10:52:34 +0000
@@ -6087,10 +6087,10 @@ void User_var_log_event::pack_info(Proto
       break;
     case DECIMAL_RESULT:
     {
-      if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH,
+      if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH + 1,
                                    MYF(MY_WME))))
         return;
-      String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH, &my_charset_bin);
+      String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH + 1, &my_charset_bin);
       my_decimal dec;
       binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0],
                         val[1]);

=== 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-05 10:52:34 +0000
@@ -99,13 +99,14 @@ 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)
+               ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1 + 1)
                : my_decimal_string_length(d));
   int result;
   if (str->alloc(length))
@@ -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-05 06:55:53 +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 'sql/protocol.cc'
--- a/sql/protocol.cc	2011-03-22 11:44:40 +0000
+++ b/sql/protocol.cc	2011-05-05 10:52:34 +0000
@@ -1063,7 +1063,7 @@ bool Protocol_text::store_decimal(const 
               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
   field_pos++;
 #endif
-  char buff[DECIMAL_MAX_STR_LENGTH];
+  char buff[DECIMAL_MAX_STR_LENGTH + 1];
   String str(buff, sizeof(buff), &my_charset_bin);
   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
   return net_store_data((uchar*) str.ptr(), str.length());
@@ -1344,7 +1344,7 @@ bool Protocol_binary::store_decimal(cons
               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
   field_pos++;
 #endif
-  char buff[DECIMAL_MAX_STR_LENGTH];
+  char buff[DECIMAL_MAX_STR_LENGTH + 1];
   String str(buff, sizeof(buff), &my_charset_bin);
   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
   return store(str.ptr(), str.length(), str.charset());

=== modified file 'sql/sql_analyse.cc'
--- a/sql/sql_analyse.cc	2011-03-22 11:44:40 +0000
+++ b/sql/sql_analyse.cc	2011-05-05 10:52:34 +0000
@@ -1102,7 +1102,7 @@ int collect_real(double *element, elemen
 int collect_decimal(uchar *element, element_count count,
                     TREE_INFO *info)
 {
-  char buff[DECIMAL_MAX_STR_LENGTH];
+  char buff[DECIMAL_MAX_STR_LENGTH + 1];
   String s(buff, sizeof(buff),&my_charset_bin);
 
   if (info->found)

=== modified file 'strings/decimal.c'
--- a/strings/decimal.c	2011-03-03 14:25:41 +0000
+++ b/strings/decimal.c	2011-05-05 10:52:34 +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 ?
@@ -368,20 +369,28 @@ int decimal2string(const decimal_t *from
   }
   else if (unlikely(len > --*to_len)) /* reserve one byte for \0 */
   {
-    int j= len-*to_len;
+    int j= len - *to_len;             /* excess printable chars */
     error= (frac && j <= frac + 1) ? E_DEC_TRUNCATED : E_DEC_OVERFLOW;
-    if (frac && j >= frac + 1) j--;
+
+    /*
+      If we need to cut more places than frac is wide, we'll end up
+      dropping the decimal point as well.  Account for this.
+    */
+    if (frac && j >= frac + 1)
+      j--;
+
     if (j > frac)
     {
-      intg-= j-frac;
+      intg_len= intg-= j-frac;
       frac= 0;
     }
     else
       frac-=j;
+    frac_len= frac;
     len= from->sign + intg_len + test(frac) + frac_len;
   }
-  *to_len=len;
-  s[len]=0;
+  *to_len= len;
+  s[len]= 0;
 
   if (from->sign)
     *s++='-';
@@ -403,14 +412,14 @@ int decimal2string(const decimal_t *from
         x*=10;
       }
     }
-    for(; fill; fill--)
+    for(; fill > 0; fill--)
       *s1++=filler;
   }
 
   fill= intg_len - intg;
   if (intg == 0)
     fill--; /* symbol 0 before digital point */
-  for(; fill; fill--)
+  for(; fill > 0; fill--)
     *s++=filler;
   if (intg)
   {
@@ -428,6 +437,7 @@ int decimal2string(const decimal_t *from
   }
   else
     *s= '0';
+
   return error;
 }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (azundris:3365 to 3367) Bug#11762799Tatiana Azundris Nurnberg5 May