From 1c1f0a62e1f68fd39ae7440042699faaffaaf7fe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Apr 2008 02:53:12 +0400 Subject: [PATCH 1/7] BUG#36139 "float, zerofill, crash with subquery" - Make convert_zerofill_number_to_string() take into account that the constant it is converting may evaluate to NULL. mysql-test/r/subselect.result: BUG#36139 "float, zerofill, crash with subquery" - Testcase mysql-test/t/subselect.test: BUG#36139 "float, zerofill, crash with subquery" - Testcase --- mysql-test/r/subselect.result | 7 +++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/item.cc | 11 ++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 2de2589fc92..349b874cbb9 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4374,4 +4374,11 @@ a4 f3 a6 1 NULL NULL 2 NULL NULL DROP TABLE t1, t2, t3, t4; +create table t1 (a float(5,4) zerofill); +create table t2 (a float(5,4),b float(2,0)); +select t1.a from t1 where +t1.a= (select b from t2 limit 1) and not +t1.a= (select a from t2 limit 1) ; +a +drop table t1; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c5edd5414e3..a60159381e1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3259,5 +3259,17 @@ GROUP BY a4; DROP TABLE t1, t2, t3, t4; +# +# BUG#36139 "float, zerofill, crash with subquery" +# +create table t1 (a float(5,4) zerofill); +create table t2 (a float(5,4),b float(2,0)); + +select t1.a from t1 where + t1.a= (select b from t2 limit 1) and not + t1.a= (select a from t2 limit 1) ; + +drop table t1; + --echo End of 5.0 tests. diff --git a/sql/item.cc b/sql/item.cc index 553ba1b152c..9ff1f8c0084 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4156,9 +4156,14 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field) String tmp(buff,sizeof(buff), field->charset()), *res; res= (*item)->val_str(&tmp); - field->prepend_zeros(res); - pos= (char *) sql_strmake (res->ptr(), res->length()); - *item= new Item_string(pos, res->length(), field->charset()); + if ((*item)->is_null()) + *item= new Item_null(); + else + { + field->prepend_zeros(res); + pos= (char *) sql_strmake (res->ptr(), res->length()); + *item= new Item_string(pos, res->length(), field->charset()); + } } From d8ebf276396252fc37169d108a993bf8b6b38157 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2008 02:14:58 +0500 Subject: [PATCH 2/7] Fixed bug #35993: memory corruption and crash with multibyte conversion. Grouping or ordering of long values in not indexed BLOB/TEXT columns with GBK or BIG5 charsets crashes the server. MySQL server uses sorting (the filesort procedure) in the temporary table to evaluate the GROUP BY clause in case of lack of suitable index. That procedure takes into account only first @max_sort_length bytes (system variable, usually 1024) of TEXT/BLOB sorting key string. The my_strnxfrm_gbk and my_strnxfrm_big5 fill temporary keys with data of whole blob length instead of @max_sort_length bytes length. That buffer overrun has been fixed. mysql-test/r/ctype_gbk.result: Added test case for bug #35993. mysql-test/t/ctype_gbk.test: Added test case for bug #35993. strings/ctype-big5.c: Fixed bug #35993: memory corruption and crash with multibyte conversion. Buffer overrun has been fixed in the my_strnxfrm_big5 function. strings/ctype-gbk.c: Fixed bug #35993: memory corruption and crash with multibyte conversion. Buffer overrun has been fixed in the my_strnxfrm_gbk function. --- mysql-test/r/ctype_gbk.result | 7 +++++++ mysql-test/t/ctype_gbk.test | 14 ++++++++++++++ strings/ctype-big5.c | 6 ++++-- strings/ctype-gbk.c | 6 ++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ctype_gbk.result b/mysql-test/r/ctype_gbk.result index 6066246a2ef..1b425134095 100644 --- a/mysql-test/r/ctype_gbk.result +++ b/mysql-test/r/ctype_gbk.result @@ -247,4 +247,11 @@ t1 CREATE TABLE `t1` ( `c2` text NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=gbk drop table t1; +CREATE TABLE t1(a MEDIUMTEXT CHARACTER SET gbk, +b MEDIUMTEXT CHARACTER SET big5); +INSERT INTO t1 VALUES +(REPEAT(0x1125,200000), REPEAT(0x1125,200000)), ('', ''), ('', ''); +SELECT a FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; +SELECT b FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; +DROP TABLES t1; End of 5.0 tests diff --git a/mysql-test/t/ctype_gbk.test b/mysql-test/t/ctype_gbk.test index 3ea696338dc..91fe50d89b9 100644 --- a/mysql-test/t/ctype_gbk.test +++ b/mysql-test/t/ctype_gbk.test @@ -53,4 +53,18 @@ alter table t1 change c1 c1 mediumtext character set gbk not null; show create table t1; drop table t1; +# +# Bug#35993: severe memory corruption and crash with multibyte conversion +# + +CREATE TABLE t1(a MEDIUMTEXT CHARACTER SET gbk, + b MEDIUMTEXT CHARACTER SET big5); +INSERT INTO t1 VALUES + (REPEAT(0x1125,200000), REPEAT(0x1125,200000)), ('', ''), ('', ''); + +SELECT a FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; +SELECT b FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; + +DROP TABLES t1; + --echo End of 5.0 tests diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 44b9951657d..c73247db404 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -307,15 +307,17 @@ static int my_strnxfrm_big5(CHARSET_INFO *cs __attribute__((unused)), { uint16 e; uint dstlen= len; + uchar *dest_end= dest + dstlen; len = srclen; - while (len--) + while (len-- && dest < dest_end) { if ((len > 0) && isbig5code(*src, *(src+1))) { e = big5strokexfrm((uint16) big5code(*src, *(src+1))); *dest++ = big5head(e); - *dest++ = big5tail(e); + if (dest < dest_end) + *dest++ = big5tail(e); src +=2; len--; } else diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 8ac7d62c9da..d0ba33aa3cc 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -2668,15 +2668,17 @@ static int my_strnxfrm_gbk(CHARSET_INFO *cs __attribute__((unused)), { uint16 e; uint dstlen= len; + uchar *dest_end= dest + dstlen; len = srclen; - while (len--) + while (len-- && dest < dest_end) { if ((len > 0) && isgbkcode(*src, *(src+1))) { e = gbksortorder((uint16) gbkcode(*src, *(src+1))); *dest++ = gbkhead(e); - *dest++ = gbktail(e); + if (dest < dest_end) + *dest++ = gbktail(e); src+=2; len--; } else From 73f7de59c2739a66dcf1a7d1d4c89a1e19fddcd1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2008 02:27:23 +0500 Subject: [PATCH 3/7] Fixed bug#36005: server crashes inside NOT IN clause subquery with impossible WHERE/HAVING clause (subselect_single_select_engine::exec). Allocation and initialization of joined table list t1, t2... of subqueries like: NOT IN (SELECT ... FROM t1,t2,... WHERE 0) is optimized out, however server tries to traverse this list. mysql-test/r/subselect3.result: Added test case for bug#36005. mysql-test/t/subselect3.test: Added test case for bug#36005. sql/sql_select.cc: Fixed bug#36005. 1. JOIN::prepare initializes JOIN::table counter (actually a size of the JOIN::join_tab array) and sets it to a number of joined tables. 2. The make_join_statistics function (when called from JOIN::optimize) allocates and fills the JOIN::join_tab array. However, when optimizing subselect has impossible (definite false) WHERE or HAVING clause, optimizer skips call to make_join_statistics and leaves JOIN::join_tab == NULL. 3. subselect_single_select_engine::exec does traversal of the JOIN::join_tab array and the server dies because array is not allocated but array counter is greater than 0. The JOIN::optimize method has been modified to reset the JOIN::table counter to 0 in cause of impossible WHERE/HAVING clause. --- mysql-test/r/subselect3.result | 9 +++++++++ mysql-test/t/subselect3.test | 13 +++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 23 insertions(+) diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index c194ba33756..5221fa09744 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -770,4 +770,13 @@ SELECT ROW(1, 2) IN (SELECT t1.a, 2 FROM t2) FROM t1 GROUP BY t1.a; ROW(1, 2) IN (SELECT t1.a, 2 FROM t2) 1 DROP TABLE t1, t2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 SELECT * FROM t1; +SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); +1 +1 +1 +1 +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index cfbde8c29cd..d7bb1f7186a 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -605,4 +605,17 @@ SELECT ROW(1, 2) IN (SELECT t1.a, 2 FROM t2) FROM t1 GROUP BY t1.a; DROP TABLE t1, t2; +# +# Bug #36005: crash in subselect with single row +# (subselect_single_select_engine::exec) +# + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 SELECT * FROM t1; + +SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); + +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 976d7322f56..11062998e6a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -832,6 +832,7 @@ JOIN::optimize() "Impossible HAVING" : "Impossible WHERE")); zero_result_cause= having_value == Item::COND_FALSE ? "Impossible HAVING" : "Impossible WHERE"; + tables= 0; error= 0; DBUG_RETURN(0); } From 415112a9406c689fa4f3ec27c1c8135d2825b14c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Apr 2008 14:22:49 +0500 Subject: [PATCH 4/7] subselect.test, subselect.result: Post-commit minor cleanup of testcase (bug#36139). mysql-test/r/subselect.result: Post-commit minor cleanup of testcase (bug#36139). mysql-test/t/subselect.test: Post-commit minor cleanup of testcase (bug#36139). --- mysql-test/r/subselect.result | 2 +- mysql-test/t/subselect.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 349b874cbb9..e56c2f07d80 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4380,5 +4380,5 @@ select t1.a from t1 where t1.a= (select b from t2 limit 1) and not t1.a= (select a from t2 limit 1) ; a -drop table t1; +drop table t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a60159381e1..527bd528f79 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3269,7 +3269,7 @@ select t1.a from t1 where t1.a= (select b from t2 limit 1) and not t1.a= (select a from t2 limit 1) ; -drop table t1; +drop table t1, t2; --echo End of 5.0 tests. From 89b866e7bfc8965046626844ee22ecd5b4e5a774 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Apr 2008 00:39:37 +0400 Subject: [PATCH 5/7] Bug#36023: Incorrect handling of zero length caused an assertion to fail. When a zero length is provided to the my_decimal_length_to_precision function along with unsigned_flag set to false it returns a negative value. For queries that employs temporary tables may cause failed assertion or excessive memory consumption while temporary table creation. Now the my_decimal_length_to_precision and the my_decimal_precision_to_length functions take unsigned_flag into account only if the length/precision argument is non-zero. mysql-test/t/type_decimal.test: Added a test case for the bug#36023: Incorrect handling of zero length caused an assertion to fail. mysql-test/r/type_decimal.result: Added a test case for the bug#36023: Incorrect handling of zero length caused an assertion to fail. sql/my_decimal.h: Bug#36023: Incorrect handling of zero length caused an assertion to fail. Now the my_decimal_length_to_precision and the my_decimal_precision_to_length functions take unsigned_flag into account only if the length/precision argument is non-zero. --- mysql-test/r/type_decimal.result | 7 +++++++ mysql-test/t/type_decimal.test | 8 ++++++++ sql/my_decimal.h | 13 +++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 2afd42f702e..03fbc898cc5 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -946,4 +946,11 @@ SELECT ROUND(20061108085411.000002); ROUND(20061108085411.000002) 20061108085411 DROP TABLE t1, t2, t3, t4, t5, t6; +create table t1(`c` decimal(9,2)); +insert into t1 values (300),(201.11); +select max(case 1 when 1 then c else null end) from t1 group by c; +max(case 1 when 1 then c else null end) +201.11 +300.00 +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 6841b3cdd68..8a81908296f 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -521,4 +521,12 @@ SELECT ROUND(20061108085411.000002); DROP TABLE t1, t2, t3, t4, t5, t6; +# +# Bug#36023: Incorrect handling of zero length caused an assertion to fail. +# +create table t1(`c` decimal(9,2)); +insert into t1 values (300),(201.11); +select max(case 1 when 1 then c else null end) from t1 group by c; +drop table t1; + --echo End of 5.0 tests diff --git a/sql/my_decimal.h b/sql/my_decimal.h index c661579ea66..6a0d05921ec 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -164,14 +164,23 @@ inline int check_result_and_overflow(uint mask, int result, my_decimal *val) inline uint my_decimal_length_to_precision(uint length, uint scale, bool unsigned_flag) { - return (uint) (length - (scale>0 ? 1:0) - (unsigned_flag ? 0:1)); + /* Precision can't be negative thus ignore unsigned_flag when length is 0. */ + DBUG_ASSERT(length || !scale); + return (uint) (length - (scale>0 ? 1:0) - + (unsigned_flag || !length ? 0:1)); } inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag) { + /* + When precision is 0 it means that original length was also 0. Thus + unsigned_flag is ignored in this case. + */ + DBUG_ASSERT(precision || !scale); set_if_smaller(precision, DECIMAL_MAX_PRECISION); - return (uint32)(precision + (scale>0 ? 1:0) + (unsigned_flag ? 0:1)); + return (uint32)(precision + (scale>0 ? 1:0) + + (unsigned_flag || !precision ? 0:1)); } inline From 8def2e0993e8b0acbff48b6f345d20ba033de21b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2008 13:41:12 -0400 Subject: [PATCH 6/7] Avoid compilation problem on AIX. --- mysys/thr_alarm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index d11883a4ea4..94ef309097a 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -14,8 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* To avoid problems with alarms in debug code, we disable DBUG here */ -#undef DBUG_OFF -#define DBUG_OFF +#define FORCE_DBUG_OFF #include #if defined(THREAD) && !defined(DONT_USE_THR_ALARM) From 57036d8a7193936682f4fe737683f965182d993c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Apr 2008 14:58:32 -0400 Subject: [PATCH 7/7] Correct failing build. --- include/my_global.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index b0a26e67d9b..e474b620d27 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -533,8 +533,12 @@ C_MODE_END #undef DBUG_OFF #endif -#if defined(_lint) && !defined(DBUG_OFF) -#define DBUG_OFF +/* We might be forced to turn debug off, if not turned off already */ +#if (defined(FORCE_DBUG_OFF) || defined(_lint)) && !defined(DBUG_OFF) +# define DBUG_OFF +# ifdef DBUG_ON +# undef DBUG_ON +# endif #endif #include