From 978bfe658a2801af8707b18950a6cc033ae05739 Mon Sep 17 00:00:00 2001 From: Sunanda Menon Date: Fri, 10 Jun 2011 07:38:09 +0200 Subject: [PATCH 1/8] Raise version number after cloning 5.0.94 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index fdfb7eae871..a06f726c738 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.94) +AM_INIT_AUTOMAKE(mysql, 5.0.95) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=94 +NDB_VERSION_BUILD=95 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From cfcd49b467dc5de004310db1ff0810842ea3bb56 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Fri, 15 Jul 2011 14:07:38 +0200 Subject: [PATCH 2/8] Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL The buffer was simply too small. In 5.5 and trunk, the size is 311 + 31, in 5.1 and below, the size is 331 client/sql_string.cc: Increase buffer size in String::set(double, ...) include/m_string.h: Increase FLOATING_POINT_BUFFER mysql-test/r/type_float.result: New test cases. mysql-test/t/type_float.test: New test cases. sql/sql_string.cc: Increase buffer size in String::set(double, ...) sql/unireg.h: Move definition of FLOATING_POINT_BUFFER --- client/sql_string.cc | 6 ++++-- include/m_string.h | 9 +++++++++ mysql-test/r/type_float.result | 12 ++++++++++++ mysql-test/t/type_float.test | 15 +++++++++++++++ sql/sql_string.cc | 6 ++++-- sql/unireg.h | 1 - 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index c9443f68e9c..0c89e1d0bca 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -119,7 +119,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 a03254ead11..94de334a050 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -216,6 +216,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 d3a136d53d2..c37b77b302d 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 1c9a3cd7fc2..545643de49f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -117,7 +117,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; @@ -186,7 +186,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 b5518809527..dd79de0781a 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -175,7 +175,6 @@ */ #define BIN_LOG_HEADER_SIZE 4 -#define FLOATING_POINT_BUFFER 331 #define DEFAULT_KEY_CACHE_NAME "default" From 1b18b486de7ff446d31fb98c9a5908350edc5120 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Mon, 18 Jul 2011 09:06:59 +0200 Subject: [PATCH 3/8] Bug#12406055 post-push fix: ignore float output --- mysql-test/r/type_float.result | 5 +---- mysql-test/t/type_float.test | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index c37b77b302d..8c9b3f4b910 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -410,13 +410,10 @@ DROP TABLE t1; # # Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL # +# Ignoring output from misc. float operations 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 95d6b6d802b..cb929702c0e 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -280,15 +280,17 @@ DROP TABLE t1; --echo # Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL --echo # +--echo # Ignoring output from misc. float operations +--disable_result_log + 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; +--enable_result_log --echo End of 5.0 tests From 138df47b4988aa59ddf3be74710c1537240b1ccc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 17 Aug 2011 13:13:44 +0300 Subject: [PATCH 4/8] changed the old @sun.com address of security trees. --- .bzr-mysql/default.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 4b2affc1529..3e92b5454d7 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "dbg_mysql_security@sun.com" -post_push_to = "dbg_mysql_security@sun.com" +post_commit_to = "MYSQL_COMMITS_SECURITY_WW@ORACLE.COM" +post_push_to = "MYSQL_COMMITS_SECURITY_WW@ORACLE.COM" tree_name = "mysql-5.0-security" From 8932ae216674f08880a6f914b9651262037175be Mon Sep 17 00:00:00 2001 From: Tatjana Azundris Nuernberg Date: Thu, 29 Sep 2011 10:47:11 +0100 Subject: [PATCH 5/8] Bug#11765687 (MySQL58677): No privilege on table / view, but can know #rows / underlying table's name 1 - If a user had SHOW VIEW and SELECT privileges on a view and this view was referencing another view, EXPLAIN SELECT on the outer view (that the user had privileges on) could reveal the structure of the underlying "inner" view as well as the number of rows in the underlying tables, even if the user had privileges on none of these referenced objects. This happened because we used DEFINER's UID ("SUID") not just for the view given in EXPLAIN, but also when checking privileges on the underlying views (where we should use the UID of the EXPLAIN's INVOKER instead). We no longer run the EXPLAIN SUID (with DEFINER's privileges). This prevents a possible exploit and makes permissions more orthogonal. 2 - EXPLAIN SELECT would reveal a view's structure even if the user did not have SHOW VIEW privileges for that view, as long as they had SELECT privilege on the underlying tables. Instead of requiring both SHOW VIEW privilege on a view and SELECT privilege on all underlying tables, we were checking for presence of either of them. We now explicitly require SHOW VIEW and SELECT privileges on the view we run EXPLAIN SELECT on, as well as all its underlying views. We also require SELECT on all relevant tables. mysql-test/r/view_grant.result: add extensive tests to illustrate desired behavior and prevent regressions (as always). mysql-test/t/view_grant.test: add extensive tests to illustrate desired behavior and prevent regressions (as always). sql/sql_view.cc: We no longer run the EXPLAIN SUID (with DEFINER's privileges). To achieve this, we use a temporary, SUID-less TABLE_LIST for the views while checking privileges. --- mysql-test/r/view_grant.result | 224 +++++++++++++++++++- mysql-test/t/view_grant.test | 368 ++++++++++++++++++++++++++++++++- sql/sql_view.cc | 34 ++- 3 files changed, 608 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index e7a50451cec..1febb54fbf4 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -64,10 +64,12 @@ create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1; create algorithm=temptable view mysqltest.v2 (c,d) as select a+1,b+1 from mysqltest.t1; create view mysqltest.v3 (c,d) as select a+1,b+1 from mysqltest.t2; create algorithm=temptable view mysqltest.v4 (c,d) as select a+1,b+1 from mysqltest.t2; +create view mysqltest.v5 (c,d) as select a+1,b+1 from mysqltest.t1; grant select on mysqltest.v1 to mysqltest_1@localhost; grant select on mysqltest.v2 to mysqltest_1@localhost; grant select on mysqltest.v3 to mysqltest_1@localhost; grant select on mysqltest.v4 to mysqltest_1@localhost; +grant show view on mysqltest.v5 to mysqltest_1@localhost; select c from mysqltest.v1; c select c from mysqltest.v2; @@ -76,6 +78,8 @@ select c from mysqltest.v3; c select c from mysqltest.v4; c +select c from mysqltest.v5; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v5' show columns from mysqltest.v1; Field Type Null Key Default Extra c bigint(12) YES NULL @@ -100,16 +104,25 @@ explain select c from mysqltest.v4; ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create view mysqltest.v4; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4' +explain select c from mysqltest.v5; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v5' +show create view mysqltest.v5; +View Create View +v5 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v5` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` +explain select c from mysqltest.v1; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +show create view mysqltest.v1; +ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' +grant show view on mysqltest.v1 to mysqltest_1@localhost; grant select on mysqltest.t1 to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v2; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY system NULL NULL NULL NULL 0 const row not found -2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create view mysqltest.v2; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2' explain select c from mysqltest.v3; @@ -120,6 +133,11 @@ explain select c from mysqltest.v4; ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create view mysqltest.v4; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4' +explain select c from mysqltest.v5; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v5' +show create view mysqltest.v5; +View Create View +v5 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v5` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` grant show view on mysqltest.* to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra @@ -135,15 +153,12 @@ show create view mysqltest.v2; View Create View v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create view mysqltest.v3; View Create View v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` explain select c from mysqltest.v4; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY system NULL NULL NULL NULL 0 const row not found -2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show create view mysqltest.v4; View Create View v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` @@ -945,4 +960,195 @@ DROP USER foo; DROP VIEW db1.v1; DROP TABLE db1.t1; DROP DATABASE db1; +Bug #11765687/#58677: +No privilege on table/view, but can know #rows / underlying table's name +create database mysqltest1; +create table mysqltest1.t1 (i int); +create table mysqltest1.t2 (j int); +create table mysqltest1.t3 (k int, secret int); +create user alice@localhost; +create user bob@localhost; +create user cecil@localhost; +create user dan@localhost; +create user eugene@localhost; +create user fiona@localhost; +create user greg@localhost; +create user han@localhost; +create user inga@localhost; +create user jamie@localhost; +create user karl@localhost; +create user lena@localhost; +create user mhairi@localhost; +create user noam@localhost; +create user olga@localhost; +create user pjotr@localhost; +create user quintessa@localhost; +grant all privileges on mysqltest1.* to alice@localhost with grant option; +... as alice +create view v1 as select * from t1; +create view v2 as select * from v1, t2; +create view v3 as select k from t3; +grant select on mysqltest1.v1 to bob@localhost; +grant show view on mysqltest1.v1 to cecil@localhost; +grant select, show view on mysqltest1.v1 to dan@localhost; +grant select on mysqltest1.t1 to dan@localhost; +grant select on mysqltest1.* to eugene@localhost; +grant select, show view on mysqltest1.v2 to fiona@localhost; +grant select, show view on mysqltest1.v2 to greg@localhost; +grant show view on mysqltest1.v1 to greg@localhost; +grant select(k) on mysqltest1.t3 to han@localhost; +grant select, show view on mysqltest1.v3 to han@localhost; +grant select on mysqltest1.t1 to inga@localhost; +grant select on mysqltest1.t2 to inga@localhost; +grant select on mysqltest1.v1 to inga@localhost; +grant select, show view on mysqltest1.v2 to inga@localhost; +grant select on mysqltest1.t1 to jamie@localhost; +grant select on mysqltest1.t2 to jamie@localhost; +grant show view on mysqltest1.v1 to jamie@localhost; +grant select, show view on mysqltest1.v2 to jamie@localhost; +grant select on mysqltest1.t1 to karl@localhost; +grant select on mysqltest1.t2 to karl@localhost; +grant select, show view on mysqltest1.v1 to karl@localhost; +grant select on mysqltest1.v2 to karl@localhost; +grant select on mysqltest1.t1 to lena@localhost; +grant select on mysqltest1.t2 to lena@localhost; +grant select, show view on mysqltest1.v1 to lena@localhost; +grant show view on mysqltest1.v2 to lena@localhost; +grant select on mysqltest1.t1 to mhairi@localhost; +grant select on mysqltest1.t2 to mhairi@localhost; +grant select, show view on mysqltest1.v1 to mhairi@localhost; +grant select, show view on mysqltest1.v2 to mhairi@localhost; +grant select on mysqltest1.t1 to noam@localhost; +grant select, show view on mysqltest1.v1 to noam@localhost; +grant select, show view on mysqltest1.v2 to noam@localhost; +grant select on mysqltest1.t2 to olga@localhost; +grant select, show view on mysqltest1.v1 to olga@localhost; +grant select, show view on mysqltest1.v2 to olga@localhost; +grant select on mysqltest1.t1 to pjotr@localhost; +grant select on mysqltest1.t2 to pjotr@localhost; +grant select, show view on mysqltest1.v2 to pjotr@localhost; +grant select, show view on mysqltest1.v1 to quintessa@localhost; +... as bob +select * from v1; +i +explain select * from v1; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as cecil +select * from v1; +ERROR 42000: SELECT command denied to user 'cecil'@'localhost' for table 'v1' +explain select * from v1; +ERROR 42000: SELECT command denied to user 'cecil'@'localhost' for table 'v1' +... as dan +select * from v1; +i +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +... as eugene +select * from v1; +i +explain select * from v1; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as fiona +select * from v2; +i j +show create view v2; +View Create View +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`alice`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `v1`.`i` AS `i`,`t2`.`j` AS `j` from (`v1` join `t2`) +explain select * from t1; +ERROR 42000: SELECT command denied to user 'fiona'@'localhost' for table 't1' +explain select * from v1; +ERROR 42000: SELECT command denied to user 'fiona'@'localhost' for table 'v1' +explain select * from t2; +ERROR 42000: SELECT command denied to user 'fiona'@'localhost' for table 't2' +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as greg +select * from v2; +i j +explain select * from v1; +ERROR 42000: SELECT command denied to user 'greg'@'localhost' for table 'v1' +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as han +select * from t3; +ERROR 42000: SELECT command denied to user 'han'@'localhost' for table 't3' +explain select * from t3; +ERROR 42000: SELECT command denied to user 'han'@'localhost' for table 't3' +select k from t3; +k +explain select k from t3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found +select * from v3; +k +explain select * from v3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found +... as inga +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as jamie +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as karl +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as lena +select * from v2; +ERROR 42000: SELECT command denied to user 'lena'@'localhost' for table 'v2' +explain select * from v2; +ERROR 42000: SELECT command denied to user 'lena'@'localhost' for table 'v2' +... as mhairi +select * from v2; +i j +explain select * from v2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found +... as noam +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as olga +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as pjotr +select * from v2; +i j +explain select * from v2; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as quintessa +select * from v1; +i +explain select * from v1; +ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table +... as root again at last: clean-up time! +drop user alice@localhost; +drop user bob@localhost; +drop user cecil@localhost; +drop user dan@localhost; +drop user eugene@localhost; +drop user fiona@localhost; +drop user greg@localhost; +drop user han@localhost; +drop user inga@localhost; +drop user jamie@localhost; +drop user karl@localhost; +drop user lena@localhost; +drop user mhairi@localhost; +drop user noam@localhost; +drop user olga@localhost; +drop user pjotr@localhost; +drop user quintessa@localhost; +drop database mysqltest1; End of 5.0 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index ff17cde5184..f06f0d58c8a 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -121,21 +121,26 @@ create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1; create algorithm=temptable view mysqltest.v2 (c,d) as select a+1,b+1 from mysqltest.t1; create view mysqltest.v3 (c,d) as select a+1,b+1 from mysqltest.t2; create algorithm=temptable view mysqltest.v4 (c,d) as select a+1,b+1 from mysqltest.t2; +# v5: SHOW VIEW, but no SELECT +create view mysqltest.v5 (c,d) as select a+1,b+1 from mysqltest.t1; grant select on mysqltest.v1 to mysqltest_1@localhost; grant select on mysqltest.v2 to mysqltest_1@localhost; grant select on mysqltest.v3 to mysqltest_1@localhost; grant select on mysqltest.v4 to mysqltest_1@localhost; +grant show view on mysqltest.v5 to mysqltest_1@localhost; connection user1; -# all selects works +# all SELECTs works, except v5 which lacks SELECT privs select c from mysqltest.v1; select c from mysqltest.v2; select c from mysqltest.v3; select c from mysqltest.v4; +--error ER_TABLEACCESS_DENIED_ERROR +select c from mysqltest.v5; # test of show coluns show columns from mysqltest.v1; show columns from mysqltest.v2; -# but explain/show do not +# explain/show fail --error ER_VIEW_NO_EXPLAIN explain select c from mysqltest.v1; --error ER_TABLEACCESS_DENIED_ERROR @@ -152,15 +157,26 @@ show create view mysqltest.v3; explain select c from mysqltest.v4; --error ER_TABLEACCESS_DENIED_ERROR show create view mysqltest.v4; +--error ER_TABLEACCESS_DENIED_ERROR +explain select c from mysqltest.v5; +show create view mysqltest.v5; -# allow to see one of underlying table -connection root; -grant select on mysqltest.t1 to mysqltest_1@localhost; -connection user1; -# EXPLAIN of view on above table works +# missing SELECT on underlying t1, no SHOW VIEW on v1 either. +--error ER_VIEW_NO_EXPLAIN explain select c from mysqltest.v1; +# missing SHOW VIEW --error ER_TABLEACCESS_DENIED_ERROR show create view mysqltest.v1; +# allow to see one of underlying table +connection root; +grant show view on mysqltest.v1 to mysqltest_1@localhost; +grant select on mysqltest.t1 to mysqltest_1@localhost; +connection user1; +# EXPLAIN works +explain select c from mysqltest.v1; +show create view mysqltest.v1; +# missing SHOW VIEW +--error ER_VIEW_NO_EXPLAIN explain select c from mysqltest.v2; --error ER_TABLEACCESS_DENIED_ERROR show create view mysqltest.v2; @@ -173,6 +189,11 @@ show create view mysqltest.v3; explain select c from mysqltest.v4; --error ER_TABLEACCESS_DENIED_ERROR show create view mysqltest.v4; +# we have SHOW VIEW on v5, and SELECT on t1 -- not enough +--error ER_TABLEACCESS_DENIED_ERROR +explain select c from mysqltest.v5; +# we can SHOW CREATE VIEW though +show create view mysqltest.v5; # allow to see any view in mysqltest database connection root; @@ -182,8 +203,12 @@ explain select c from mysqltest.v1; show create view mysqltest.v1; explain select c from mysqltest.v2; show create view mysqltest.v2; +# have SHOW VIEW | SELECT on v3, but no SELECT on t2 +--error ER_VIEW_NO_EXPLAIN explain select c from mysqltest.v3; show create view mysqltest.v3; +# have SHOW VIEW | SELECT on v4, but no SELECT on t2 +--error ER_VIEW_NO_EXPLAIN explain select c from mysqltest.v4; show create view mysqltest.v4; @@ -1232,7 +1257,336 @@ DROP TABLE db1.t1; DROP DATABASE db1; connection default; + + +--echo Bug #11765687/#58677: +--echo No privilege on table/view, but can know #rows / underlying table's name + +# As a root-like user +connect (root,localhost,root,,test); +connection root; + +create database mysqltest1; +create table mysqltest1.t1 (i int); +create table mysqltest1.t2 (j int); +create table mysqltest1.t3 (k int, secret int); + +create user alice@localhost; +create user bob@localhost; +create user cecil@localhost; +create user dan@localhost; +create user eugene@localhost; +create user fiona@localhost; +create user greg@localhost; +create user han@localhost; +create user inga@localhost; +create user jamie@localhost; +create user karl@localhost; +create user lena@localhost; +create user mhairi@localhost; +create user noam@localhost; +create user olga@localhost; +create user pjotr@localhost; +create user quintessa@localhost; + +grant all privileges on mysqltest1.* to alice@localhost with grant option; + +# +--echo ... as alice +connect (test11765687,localhost,alice,,mysqltest1); +connection test11765687; + +create view v1 as select * from t1; +create view v2 as select * from v1, t2; +create view v3 as select k from t3; + +grant select on mysqltest1.v1 to bob@localhost; + +grant show view on mysqltest1.v1 to cecil@localhost; + +grant select, show view on mysqltest1.v1 to dan@localhost; +grant select on mysqltest1.t1 to dan@localhost; + +grant select on mysqltest1.* to eugene@localhost; + +grant select, show view on mysqltest1.v2 to fiona@localhost; + +grant select, show view on mysqltest1.v2 to greg@localhost; +grant show view on mysqltest1.v1 to greg@localhost; + +grant select(k) on mysqltest1.t3 to han@localhost; +grant select, show view on mysqltest1.v3 to han@localhost; + +grant select on mysqltest1.t1 to inga@localhost; +grant select on mysqltest1.t2 to inga@localhost; +grant select on mysqltest1.v1 to inga@localhost; +grant select, show view on mysqltest1.v2 to inga@localhost; + +grant select on mysqltest1.t1 to jamie@localhost; +grant select on mysqltest1.t2 to jamie@localhost; +grant show view on mysqltest1.v1 to jamie@localhost; +grant select, show view on mysqltest1.v2 to jamie@localhost; + +grant select on mysqltest1.t1 to karl@localhost; +grant select on mysqltest1.t2 to karl@localhost; +grant select, show view on mysqltest1.v1 to karl@localhost; +grant select on mysqltest1.v2 to karl@localhost; + +grant select on mysqltest1.t1 to lena@localhost; +grant select on mysqltest1.t2 to lena@localhost; +grant select, show view on mysqltest1.v1 to lena@localhost; +grant show view on mysqltest1.v2 to lena@localhost; + +grant select on mysqltest1.t1 to mhairi@localhost; +grant select on mysqltest1.t2 to mhairi@localhost; +grant select, show view on mysqltest1.v1 to mhairi@localhost; +grant select, show view on mysqltest1.v2 to mhairi@localhost; + +grant select on mysqltest1.t1 to noam@localhost; +grant select, show view on mysqltest1.v1 to noam@localhost; +grant select, show view on mysqltest1.v2 to noam@localhost; + +grant select on mysqltest1.t2 to olga@localhost; +grant select, show view on mysqltest1.v1 to olga@localhost; +grant select, show view on mysqltest1.v2 to olga@localhost; + +grant select on mysqltest1.t1 to pjotr@localhost; +grant select on mysqltest1.t2 to pjotr@localhost; +grant select, show view on mysqltest1.v2 to pjotr@localhost; + +grant select, show view on mysqltest1.v1 to quintessa@localhost; + +disconnect test11765687; + +# +--echo ... as bob +connect (test11765687,localhost,bob,,mysqltest1); +connection test11765687; + +select * from v1; # Should succeed. +--error ER_VIEW_NO_EXPLAIN +explain select * from v1; # fail, no SHOW_VIEW + +disconnect test11765687; + +# +--echo ... as cecil +connect (test11765687,localhost,cecil,,mysqltest1); +connection test11765687; + +--error ER_TABLEACCESS_DENIED_ERROR +select * from v1; # fail, no SELECT +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from v1; # fail, no SELECT + +disconnect test11765687; + +# +--echo ... as dan +connect (test11765687,localhost,dan,,mysqltest1); +connection test11765687; + +select * from v1; # Should succeed. +explain select * from v1; # Should succeed. + +disconnect test11765687; + +# +--echo ... as eugene +connect (test11765687,localhost,eugene,,mysqltest1); +connection test11765687; + +select * from v1; # Should succeed. +--error ER_VIEW_NO_EXPLAIN +explain select * from v1; # fail, no SHOW_VIEW + +disconnect test11765687; + +# +--echo ... as fiona +connect (test11765687,localhost,fiona,,mysqltest1); +connection test11765687; + +select * from v2; # Should succeed. +show create view v2; # Should succeed, but... +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from t1; # fail, shouldn't see t1! +--error ER_TABLEACCESS_DENIED_ERROR +# err msg must give view name, no table names!! +explain select * from v1; # fail, have no privs on v1! +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from t2; # fail, have no privs on t2! +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; # fail, shouldn't see t2! + +disconnect test11765687; + +# +--echo ... as greg +connect (test11765687,localhost,greg,,mysqltest1); +connection test11765687; + +select * from v2; # Should succeed. +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from v1; # fail; no SELECT on v1! +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; # fail; no SELECT on v1! + +disconnect test11765687; + +# +--echo ... as han +connect (test11765687,localhost,han,,mysqltest1); +connection test11765687; + +--error ER_TABLEACCESS_DENIED_ERROR +select * from t3; # don't have privs on all columns, +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from t3; # so EXPLAIN on "forbidden" columns should fail. +select k from t3; # but we do have SELECT on column k though, +explain select k from t3; # so EXPLAIN just on k should work, +select * from v3; # and so should SELECT on view only using allowed columns +explain select * from v3; # as should the associated EXPLAIN + +disconnect test11765687; + +# +--echo ... as inga +connect (test11765687,localhost,inga,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel on t1/t2, only sel v1 +# fail: lacks show on v1 +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as jamie +connect (test11765687,localhost,jamie,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel on t1/t2, only show v1 +# fail: lacks sel on v1 +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as karl +connect (test11765687,localhost,karl,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel only on v2, sel on t1/t2, sel/show v1 +# fail: lacks show on v2 +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as lena + +connect (test11765687,localhost,lena,,mysqltest1); +connection test11765687; +--error ER_TABLEACCESS_DENIED_ERROR +select * from v2; +# has show only on v2, sel on t1/t2, sel/show v1 +# fail: lacks sel on v2 +--error ER_TABLEACCESS_DENIED_ERROR +explain select * from v2; +disconnect test11765687; + +# +--echo ... as mhairi +connect (test11765687,localhost,mhairi,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel on t1/t2, sel/show v1 +explain select * from v2; +disconnect test11765687; + +# +--echo ... as noam +connect (test11765687,localhost,noam,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel only on t1, sel/show v1 (no sel on t2!) +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as olga +connect (test11765687,localhost,olga,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel only on t2, sel/show v1 (no sel on t1!) +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as pjotr +connect (test11765687,localhost,pjotr,,mysqltest1); +connection test11765687; + +select * from v2; +# has sel/show on v2, sel only on t2, nothing on v1 +# fail: lacks show on v1 +--error ER_VIEW_NO_EXPLAIN +explain select * from v2; +disconnect test11765687; + +# +--echo ... as quintessa +connect (test11765687,localhost,quintessa,,mysqltest1); +connection test11765687; + +select * from v1; # Should succeed. +--error ER_VIEW_NO_EXPLAIN +explain select * from v1; # fail: lacks select on t1 + +disconnect test11765687; + +# cleanup + +# +--echo ... as root again at last: clean-up time! +connection root; + +drop user alice@localhost; +drop user bob@localhost; +drop user cecil@localhost; +drop user dan@localhost; +drop user eugene@localhost; +drop user fiona@localhost; +drop user greg@localhost; +drop user han@localhost; +drop user inga@localhost; +drop user jamie@localhost; +drop user karl@localhost; +drop user lena@localhost; +drop user mhairi@localhost; +drop user noam@localhost; +drop user olga@localhost; +drop user pjotr@localhost; +drop user quintessa@localhost; + +drop database mysqltest1; + +disconnect root; + +connection default; + --echo End of 5.0 tests. + + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 07580663f24..c318f79eec1 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1148,8 +1148,38 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if (!table->prelocking_placeholder && (old_lex->sql_command == SQLCOM_SELECT && old_lex->describe)) { - if (check_table_access(thd, SELECT_ACL, view_tables, 1) && - check_table_access(thd, SHOW_VIEW_ACL, table, 1)) + /* + The user we run EXPLAIN as (either the connected user who issued + the EXPLAIN statement, or the definer of a SUID stored routine + which contains the EXPLAIN) should have both SHOW_VIEW_ACL and + SELECT_ACL on the view being opened as well as on all underlying + views since EXPLAIN will disclose their structure. This user also + should have SELECT_ACL on all underlying tables of the view since + this EXPLAIN will disclose information about the number of rows in it. + + To perform this privilege check we create auxiliary TABLE_LIST object + for the view in order a) to avoid trashing "table->grant" member for + original table list element, which contents can be important at later + stage for column-level privilege checking b) get TABLE_LIST object + with "security_ctx" member set to 0, i.e. forcing check_table_access() + to use active user's security context. + + There is no need for creating similar copies of table list elements + for underlying tables since they are just have been constructed and + thus have TABLE_LIST::security_ctx == 0 and fresh TABLE_LIST::grant + member. + + Finally at this point making sure we have SHOW_VIEW_ACL on the views + will suffice as we implicitly require SELECT_ACL anyway. + */ + + TABLE_LIST view; + bzero((char *)&view, sizeof(TABLE_LIST)); + view.db= table->db; + view.table_name= table->table_name; + + if (check_table_access(thd, SELECT_ACL, view_tables, 1) || + check_table_access(thd, SHOW_VIEW_ACL, &view, 1)) { my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0)); goto err; From d740f9e603378c2ba9bbfacd111f6fe9c6728b78 Mon Sep 17 00:00:00 2001 From: Tatjana Azundris Nuernberg Date: Thu, 6 Oct 2011 11:23:46 +0100 Subject: [PATCH 6/8] additional clean-up for 11765687 --- sql/sql_view.cc | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c318f79eec1..3ae35e5cfe0 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1164,22 +1164,23 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, with "security_ctx" member set to 0, i.e. forcing check_table_access() to use active user's security context. - There is no need for creating similar copies of table list elements - for underlying tables since they are just have been constructed and - thus have TABLE_LIST::security_ctx == 0 and fresh TABLE_LIST::grant - member. + There is no need for creating similar copies of TABLE_LIST elements + for underlying tables since they just have been constructed and thus + have TABLE_LIST::security_ctx == 0 and fresh TABLE_LIST::grant member. Finally at this point making sure we have SHOW_VIEW_ACL on the views will suffice as we implicitly require SELECT_ACL anyway. */ - TABLE_LIST view; - bzero((char *)&view, sizeof(TABLE_LIST)); - view.db= table->db; - view.table_name= table->table_name; + TABLE_LIST view_no_suid; + bzero(static_cast(&view_no_suid), sizeof(TABLE_LIST)); + view_no_suid.db= table->db; + view_no_suid.table_name= table->table_name; + + DBUG_ASSERT(view_tables == NULL || view_tables->security_ctx == NULL); if (check_table_access(thd, SELECT_ACL, view_tables, 1) || - check_table_access(thd, SHOW_VIEW_ACL, &view, 1)) + check_table_access(thd, SHOW_VIEW_ACL, &view_no_suid, 1)) { my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0)); goto err; From a6145f4b62bd264ad32d2dade98eda0cc6de0dba Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Fri, 14 Oct 2011 10:09:53 +0200 Subject: [PATCH 7/8] Bug#12563865 ROUNDED,TMP_BUF,DECIMAL_VALUE STACK CORRUPTION IN ALL VERSIONS >=5.0 Buffer over-run on all platforms, crash on windows, wrong result on other platforms, when rounding numbers which start with 999999999 and have precision = 9 or 18 or 27 or 36 ... mysql-test/r/type_newdecimal.result: New test cases. mysql-test/t/type_newdecimal.test: New test cases. sql/my_decimal.h: Add sanity checking code, to catch buffer over/under-run. strings/decimal.c: The original initialization of intg1 (add 1 if buf[0] == DIG_MAX) will set p1 to point outside the buffer, and the loop to copy the original value while (buf0 < p0) *(--p1) = *(--p0); will overwrite memory outside the my_decimal object. --- mysql-test/r/type_newdecimal.result | 44 +++++++++++++++++++++++++++++ mysql-test/t/type_newdecimal.test | 21 ++++++++++++++ sql/my_decimal.h | 30 ++++++++++++++++++++ strings/decimal.c | 21 ++++++++------ 4 files changed, 108 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 90b6f524692..43caaa2239b 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1539,4 +1539,48 @@ select * from t1; 5.05 / 0.014 360.714286 DROP TABLE t1; +# +# Bug#12563865 +# ROUNDED,TMP_BUF,DECIMAL_VALUE STACK CORRUPTION IN ALL VERSIONS >=5.0 +# +SELECT substring(('M') FROM (999999999999999999999999999999999999999999999999999999999999999999999999999999999)) AS foo; +foo + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +SELECT min(999999999999999999999999999999999999999999999999999999999999999999999999999999999) AS foo; +foo +999999999999999999999999999999999999999999999999999999999999999999999999999999999 +SELECT multipolygonfromtext(('4294967294.1'),(999999999999999999999999999999999999999999999999999999999999999999999999999999999)) AS foo; +foo +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +SELECT convert((999999999999999999999999999999999999999999999999999999999999999999999999999999999), decimal(30,30)) AS foo; +foo +0.999999999999999999999999999999 +Warnings: +Error 1264 Out of range value adjusted for column 'foo' at row 1 +SELECT bit_xor(999999999999999999999999999999999999999999999999999999999999999999999999999999999) AS foo; +foo +9223372036854775807 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +SELECT -(999999999999999999999999999999999999999999999999999999999999999999999999999999999) AS foo; +foo +-999999999999999999999999999999999999999999999999999999999999999999999999999999999 +SELECT date_sub((999999999999999999999999999999999999999999999999999999999999999999999999999999999), +interval ((SELECT date_add((0x77500000), +interval ('Oml') second))) +day_minute) +AS foo; +foo +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1292 Truncated incorrect datetime value: '9223372036854775807' +SELECT truncate(999999999999999999999999999999999999999999999999999999999999999999999999999999999, 28) AS foo; +foo +999999999999999999999999999999999999999999999999999999999999999999999999999999999 End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index a5331582df6..a55951caf63 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1235,4 +1235,25 @@ show create table t1; select * from t1; DROP TABLE t1; +--echo # +--echo # Bug#12563865 +--echo # ROUNDED,TMP_BUF,DECIMAL_VALUE STACK CORRUPTION IN ALL VERSIONS >=5.0 +--echo # + +let $nine_81= +999999999999999999999999999999999999999999999999999999999999999999999999999999999; + +eval SELECT substring(('M') FROM ($nine_81)) AS foo; +eval SELECT min($nine_81) AS foo; +eval SELECT multipolygonfromtext(('4294967294.1'),($nine_81)) AS foo; +eval SELECT convert(($nine_81), decimal(30,30)) AS foo; +eval SELECT bit_xor($nine_81) AS foo; +eval SELECT -($nine_81) AS foo; +eval SELECT date_sub(($nine_81), + interval ((SELECT date_add((0x77500000), + interval ('Oml') second))) + day_minute) +AS foo; +eval SELECT truncate($nine_81, 28) AS foo; + --echo End of 5.0 tests diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 6a0d05921ec..ee023438f20 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -86,12 +86,31 @@ inline int my_decimal_int_part(uint precision, uint decimals) class my_decimal :public decimal_t { + /* + Several of the routines in strings/decimal.c have had buffer + overrun/underrun problems. These are *not* caught by valgrind. + To catch them, we allocate dummy fields around the buffer, + and test that their values do not change. + */ +#if !defined(DBUG_OFF) + int foo1; +#endif + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH]; +#if !defined(DBUG_OFF) + int foo2; + static const int test_value= 123; +#endif + public: void init() { +#if !defined(DBUG_OFF) + foo1= test_value; + foo2= test_value; +#endif len= DECIMAL_BUFF_LENGTH; buf= buffer; #if !defined (HAVE_purify) && !defined(DBUG_OFF) @@ -104,6 +123,17 @@ public: { init(); } + ~my_decimal() + { + sanity_check(); + } + + void sanity_check() + { + DBUG_ASSERT(foo1 == test_value); + DBUG_ASSERT(foo2 == test_value); + } + void fix_buffer_pointer() { buf= buffer; } bool sign() const { return decimal_t::sign; } diff --git a/strings/decimal.c b/strings/decimal.c index 1498aec15a1..87faff9b4cd 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1480,9 +1480,8 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, { int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit), - intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len, - intg1=ROUND_UP(from->intg + - (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX))); + intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len; + dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0; int first_dig; @@ -1497,6 +1496,12 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, default: DBUG_ASSERT(0); } + /* + For my_decimal we always use len == DECIMAL_BUFF_LENGTH == 9 + For internal testing here (ifdef MAIN) we always use len == 100/4 + */ + DBUG_ASSERT(from->len == to->len); + if (unlikely(frac0+intg0 > len)) { frac0=len-intg0; @@ -1510,17 +1515,17 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, return E_DEC_OK; } - if (to != from || intg1>intg0) + if (to != from) { dec1 *p0= buf0+intg0+max(frac1, frac0); - dec1 *p1= buf1+intg1+max(frac1, frac0); + dec1 *p1= buf1+intg0+max(frac1, frac0); + + DBUG_ASSERT(p0 - buf0 <= len); + DBUG_ASSERT(p1 - buf1 <= len); while (buf0 < p0) *(--p1) = *(--p0); - if (unlikely(intg1 > intg0)) - to->buf[0]= 0; - intg0= intg1; buf0=to->buf; buf1=to->buf; to->sign=from->sign; From beedf6b261b243ec0a2332162bface6ec7d58dd0 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 12 Dec 2011 14:07:02 +0100 Subject: [PATCH 8/8] Bug#12361113: CRASH WHEN "LOAD INDEX INTO CACHE" WITH TOO SMALL KEY CACHE The server crashed on division by zero because the key cache was not initialized and the block length was 0 which was used in a division. The fix was to not allow CACHE INDEX if the key cache was not initiallized. Thus never try LOAD INDEX INTO CACHE for an uninitialized key cache. Also added some windows files/directories to .bzrignore. --- .bzrignore | 9 +++++++++ myisam/mi_preload.c | 3 +++ mysql-test/r/key_cache.result | 16 ++++++++++++++++ mysql-test/t/key_cache.test | 16 ++++++++++++++++ sql/sql_table.cc | 5 +++++ 5 files changed, 49 insertions(+) diff --git a/.bzrignore b/.bzrignore index 2b5b42cb87f..184ed9fe235 100644 --- a/.bzrignore +++ b/.bzrignore @@ -8,6 +8,7 @@ *.core *.d *.da +*.dir *.exe *.gcda *.gcno @@ -25,6 +26,7 @@ *.pdb *.reject *.res +*.rule *.sbr *.so *.so.* @@ -32,13 +34,19 @@ *.user *.vcproj *.vcproj.cmake +*.vcxproj +*.vcxproj.filters */*.dir/* +Debug +MySql.sdf +Win32 */*_pure_*warnings */.deps */.libs/* */.pure */debug/* */release/* +RelWithDebInfo *~ .*.swp ./CMakeCache.txt @@ -83,6 +91,7 @@ BitKeeper/tmp/* BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/gone CMakeFiles/* +CMakeFiles COPYING COPYING.LIB Docs/#manual.texi# diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c index c73c70962ed..f53fcd2e1ee 100644 --- a/myisam/mi_preload.c +++ b/myisam/mi_preload.c @@ -54,6 +54,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos) DBUG_RETURN(0); + /* Preload into a non initialized key cache should never happen. */ + DBUG_ASSERT(share->key_cache->key_cache_inited); + block_length= keyinfo[0].block_length; if (ignore_leaves) diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index 9ada5dc0784..6513c4eb374 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -368,3 +368,19 @@ Variable_name Value key_cache_block_size 1536 SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; DROP TABLE t1; +# +# Bug#12361113: crash when load index into cache +# +# Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1, 1); +CACHE INDEX t1 in key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +# The bug crashed the server at LOAD INDEX below. Now it will succeed +# since the default cache is used due to CACHE INDEX failed for +# key_cache_none. +LOAD INDEX INTO CACHE t1; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +DROP TABLE t1; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index 4c14dc96aaa..9d865b9b5fe 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -247,3 +247,19 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; DROP TABLE t1; # End of 4.1 tests + +--echo # +--echo # Bug#12361113: crash when load index into cache +--echo # + +--echo # Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1, 1); +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 in key_cache_none; +--echo # The bug crashed the server at LOAD INDEX below. Now it will succeed +--echo # since the default cache is used due to CACHE INDEX failed for +--echo # key_cache_none. +LOAD INDEX INTO CACHE t1; +DROP TABLE t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4320cef2c49..2bb758f8b86 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2680,6 +2680,11 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, DBUG_RETURN(TRUE); } pthread_mutex_unlock(&LOCK_global_system_variables); + if (!key_cache->key_cache_inited) + { + my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str); + DBUG_RETURN(TRUE); + } check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,