From 4858032176df372dcedeb16cbad968dd7db48f9f Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Tue, 28 Feb 2006 13:36:41 +0400 Subject: [PATCH 1/5] Fix for bug#17602 Server crash on AVG/SUM over DECIMAL column(2nd ver) The table may be corrupted and decimal columns may have invalid values in this case. To prevent crash we need to check that decimal column has allowable value. In case of invalid value generate warning and set the value to 0. --- strings/decimal.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/strings/decimal.c b/strings/decimal.c index 5fb37d374a2..8786a513945 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1347,6 +1347,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) } from+=i; *buf=x ^ mask; + if (((uint32)*buf) >= powers10[intg0x+1]) + goto err; if (buf > to->buf || *buf != 0) buf++; else @@ -1356,6 +1358,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) { DBUG_ASSERT(sizeof(dec1) == 4); *buf=mi_sint4korr(from) ^ mask; + if (((uint32)*buf) > DIG_MAX) + goto err; if (buf > to->buf || *buf != 0) buf++; else @@ -1366,6 +1370,8 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) { DBUG_ASSERT(sizeof(dec1) == 4); *buf=mi_sint4korr(from) ^ mask; + if (((uint32)*buf) > DIG_MAX) + goto err; buf++; } if (frac0x) @@ -1381,10 +1387,17 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) default: DBUG_ASSERT(0); } *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; + if (((uint32)*buf) > DIG_MAX) + goto err; buf++; } my_afree(d_copy); return error; + +err: + my_afree(d_copy); + decimal_make_zero(((decimal_t*) to)); + return(E_DEC_BAD_NUM); } /* From 0ce39664b657ee404faf44aba420443146c0de20 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Tue, 28 Feb 2006 19:30:30 +0300 Subject: [PATCH 2/5] Fixed bug#14169: type of group_concat() result changed to blob if tmp_table was used In a simple queries a result of the GROUP_CONCAT() function was always of varchar type. But if length of GROUP_CONCAT() result is greater than 512 chars and temporary table is used during select then the result is converted to blob, due to policy to not to store fields longer than 512 chars in tmp table as varchar fields. In order to provide consistent behaviour, result of GROUP_CONCAT() now will always be converted to blob if it is longer than 512 chars. Item_func_group_concat::field_type() is modified accordingly. --- sql/item_sum.h | 7 +++++++ tests/mysql_client_test.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/sql/item_sum.h b/sql/item_sum.h index a8242d76287..a38530a502c 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1116,6 +1116,13 @@ public: enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} const char *func_name() const { return "group_concat"; } virtual Item_result result_type () const { return STRING_RESULT; } + enum_field_types field_type() const + { + if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB) + return FIELD_TYPE_BLOB; + else + return MYSQL_TYPE_VARCHAR; + } void clear(); bool add(); void reset_field() { DBUG_ASSERT(0); } // not used diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index c265375a263..8ec5bcd6f0c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -14841,6 +14841,40 @@ static void test_bug15613() } /* + Bug#14169: type of group_concat() result changed to blob if tmp_table was used +*/ +static void test_bug14169() +{ + MYSQL_STMT *stmt; + const char *stmt_text; + MYSQL_RES *res; + MYSQL_FIELD *field; + int rc; + + myheader("test_bug14169"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + rc= mysql_query(mysql, "set session group_concat_max_len=1024"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (f1 int unsigned, f2 varchar(255))"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1,repeat('a',255))," + "(2,repeat('b',255))"); + myquery(rc); + stmt= mysql_stmt_init(mysql); + stmt_text= "select f2,group_concat(f1) from t1 group by f2"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + myquery(rc); + res= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_fields(res); + if (!opt_silent) + printf("GROUP_CONCAT() result type %i", field[1].type); + DIE_UNLESS(field[1].type == MYSQL_TYPE_BLOB); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +}/* Read and parse arguments and MySQL options from my.cnf */ @@ -15105,6 +15139,7 @@ static struct my_tests_st my_tests[]= { { "test_bug16143", test_bug16143 }, { "test_bug16144", test_bug16144 }, { "test_bug15613", test_bug15613 }, + { "test_bug14169", test_bug14169 }, { 0, 0 } }; From a3ea8947584dcac29f7cddf35c804e84bba8bb21 Mon Sep 17 00:00:00 2001 From: "aivanov@mysql.com" <> Date: Wed, 1 Mar 2006 16:21:01 +0300 Subject: [PATCH 3/5] Fixed BUG #16175: Memory leak in rpl_trigger.test Allocating/freeing memory for the db member of THD is wholy managed by slave thread. --- sql/sql_db.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 357d2d5a21f..63a7b1df8f1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1098,7 +1098,8 @@ err: bool mysql_change_db(THD *thd, const char *name, bool no_access_check) { int length, db_length; - char *dbname=my_strdup((char*) name,MYF(MY_WME)); + char *dbname= thd->slave_thread ? (char *) name : + my_strdup((char *) name, MYF(MY_WME)); char path[FN_REFLEN]; HA_CREATE_INFO create; bool system_db= 0; @@ -1118,7 +1119,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) system_db= 1; goto end; } - x_free(dbname); /* purecov: inspected */ + if (!(thd->slave_thread)) + x_free(dbname); /* purecov: inspected */ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ @@ -1126,7 +1128,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) if (check_db_name(dbname)) { my_error(ER_WRONG_DB_NAME, MYF(0), dbname); - x_free(dbname); + if (!(thd->slave_thread)) + x_free(dbname); DBUG_RETURN(1); } DBUG_PRINT("info",("Use database: %s", dbname)); @@ -1156,7 +1159,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) dbname); mysql_log.write(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), sctx->priv_user, sctx->priv_host, dbname); - my_free(dbname,MYF(0)); + if (!(thd->slave_thread)) + my_free(dbname,MYF(0)); DBUG_RETURN(1); } } @@ -1168,7 +1172,8 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) if (my_access(path,F_OK)) { my_error(ER_BAD_DB_ERROR, MYF(0), dbname); - my_free(dbname,MYF(0)); + if (!(thd->slave_thread)) + my_free(dbname,MYF(0)); DBUG_RETURN(1); } end: From 3a325cb81e07cfc949396ea05baf199a70268614 Mon Sep 17 00:00:00 2001 From: "msvensson@shellback.(none)" <> Date: Wed, 1 Mar 2006 15:21:03 +0100 Subject: [PATCH 4/5] Bug#2845 client fails to reconnect if using TCP/IP - Change to use non blocking read to empty channel in case of too large sd number - Don't check for too large socket number on Windows. --- sql/net_serv.cc | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index b3ee28607ad..c5794fb4d25 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -229,8 +229,12 @@ static int net_data_is_ready(my_socket sd) struct timeval tv; int res; +#ifndef __WIN__ + /* Windows uses an _array_ of 64 fd's as default, so it's safe */ if (sd >= FD_SETSIZE) return -1; + #define NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE +#endif FD_ZERO(&sfds); FD_SET(sd, &sfds); @@ -271,7 +275,7 @@ void net_clear(NET *net) int count, ready; DBUG_ENTER("net_clear"); #if !defined(EMBEDDED_LIBRARY) - while((ready= net_data_is_ready(net->vio->sd)) != 0) + while((ready= net_data_is_ready(net->vio->sd)) > 0) { /* The socket is ready */ if ((count= vio_read(net->vio, (char*) (net->buff), @@ -286,15 +290,27 @@ void net_clear(NET *net) } else { - /* No data to read and 'net_data_is_ready' returned "don't know" */ - if (ready == -1) - break; - DBUG_PRINT("info",("socket ready but only EOF to read - disconnected")); net->error= 2; break; } } +#ifdef NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE + /* 'net_data_is_ready' returned "don't know" */ + if (ready == -1) + { + /* Read unblocking to clear net */ + my_bool old_mode; + if (!vio_blocking(net->vio, FALSE, &old_mode)) + { + while ((count= vio_read(net->vio, (char*) (net->buff), + (uint32) net->max_packet)) > 0) + DBUG_PRINT("info",("skipped %d bytes from file: %s", + count, vio_description(net->vio))); + vio_blocking(net->vio, TRUE, &old_mode); + } + } +#endif #endif net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; From b802826fc90d3f6039bab1af2842d6a5009f4aa0 Mon Sep 17 00:00:00 2001 From: "msvensson@shellback.(none)" <> Date: Wed, 1 Mar 2006 15:22:47 +0100 Subject: [PATCH 5/5] Dont' run the mysql_protocols on Windows --- mysql-test/t/mysql_protocols.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/mysql_protocols.test b/mysql-test/t/mysql_protocols.test index 0253c2b5d17..5eba780420c 100644 --- a/mysql-test/t/mysql_protocols.test +++ b/mysql-test/t/mysql_protocols.test @@ -1,5 +1,7 @@ # Embedded server doesn't support external clients --source include/not_embedded.inc +# Windows does not have SOCKET, but will try to create a PIPE as well as MEMORY +--source include/not_windows.inc # test for Bug #4998 "--protocol doesn't reject bad values"