summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql_com.h10
-rw-r--r--mysql-test/r/explain.result12
-rw-r--r--mysql-test/r/loaddata.result6
-rw-r--r--mysql-test/r/ps.result12
-rw-r--r--mysql-test/r/trigger.result23
-rw-r--r--mysql-test/t/explain.test13
-rw-r--r--mysql-test/t/loaddata.test14
-rw-r--r--mysql-test/t/trigger.test31
-rw-r--r--sql/item_strfunc.cc3
-rw-r--r--sql/mysqld.cc46
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/net_serv.cc4
-rw-r--r--sql/sp_head.cc34
-rw-r--r--sql/sp_head.h4
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_connect.cc7
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_load.cc11
-rw-r--r--sql/sql_select.cc3
19 files changed, 180 insertions, 58 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h
index e4e34141d43..e2baa06b160 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -300,6 +300,16 @@ typedef struct st_net {
/** Client library sqlstate buffer. Set along with the error message. */
char sqlstate[SQLSTATE_LENGTH+1];
void *extension;
+#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+ /*
+ Controls whether a big packet should be skipped.
+
+ Initially set to FALSE by default. Unauthenticated sessions must have
+ this set to FALSE so that the server can't be tricked to read packets
+ indefinitely.
+ */
+ my_bool skip_big_packet;
+#endif
} NET;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 9740303c00e..7042a2c6f6c 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -246,4 +246,16 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select '1' AS `f1`,`test`.`t2`.`f2` AS `f2` from `test`.`t2` where (`test`.`t2`.`f2` = 1)
drop table t1,t2;
+#
+# Bug #48419: another explain crash..
+#
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (b BLOB, KEY b(b(100)));
+INSERT INTO t2 VALUES ('1'), ('2'), ('3');
+FLUSH TABLES;
+EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND t.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+DROP TABLE t1, t2;
End of 5.1 tests.
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index 9969147a93e..7a79603adb3 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -202,12 +202,6 @@ select * from t1;
a b c
10 NULL Ten
15 NULL Fifteen
-show variables like "secure_file_pri%";
-Variable_name Value
-secure_file_priv MYSQLTEST_VARDIR
-select @@secure_file_priv;
-@@secure_file_priv
-MYSQLTEST_VARDIR
set @@secure_file_priv= 0;
ERROR HY000: Variable 'secure_file_priv' is a read only variable
truncate table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 5ac8ec78f2d..16f6657ceeb 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -155,24 +155,24 @@ execute stmt1 ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
-4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
execute stmt1 ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
-4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
-4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found
+5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
deallocate prepare stmt1;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 1cc9e57772b..e303c16fdd2 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -2128,6 +2128,29 @@ Warning 1048 Column 'id' cannot be null
Warning 1048 Column 'id' cannot be null
DROP TRIGGER t1_bu;
DROP TABLE t1,t2;
+#
+# Bug#50755: Crash if stored routine def contains version comments
+#
+DROP DATABASE IF EXISTS db1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1, t2;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE t1 (b INT);
+CREATE TABLE t2 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1);
+# Used to crash
+SHOW TRIGGERS IN db1;
+Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
+Warnings:
+Warning 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
+INSERT INTO t2 VALUES (1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
+SELECT * FROM t1;
+b
+# Work around Bug#45235
+DROP DATABASE db1;
+USE test;
End of 5.1 tests.
#
# Bug#34453 Can't change size of file (Errcode: 1224)
diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test
index 30366f6f67e..72406110de1 100644
--- a/mysql-test/t/explain.test
+++ b/mysql-test/t/explain.test
@@ -210,4 +210,17 @@ explain extended select * from t1 where f1=1;
explain extended select * from t1 join t2 on f1=f2 where f1=1;
drop table t1,t2;
+--echo #
+--echo # Bug #48419: another explain crash..
+--echo #
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (b BLOB, KEY b(b(100)));
+INSERT INTO t2 VALUES ('1'), ('2'), ('3');
+
+FLUSH TABLES;
+
+EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND t.a);
+
+DROP TABLE t1, t2;
+
--echo End of 5.1 tests.
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index e5f0a1d7eba..126bd5c8838 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -153,10 +153,16 @@ select * from t1;
#
# It should not be possible to load from a file outside of vardir
---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-show variables like "secure_file_pri%";
---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-select @@secure_file_priv;
+## The following lines were disabled because of patch for
+## bug 50373. MYSQLTEST_VARDIR doesn't rewrite symlinks
+## to real paths, but this is done for secure_file_priv.
+## Because of this the result can't be replaced if the
+## test suite runs with the --mem option which creates
+## symlinks to the ramdisk.
+#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+#show variables like "secure_file_pri%";
+#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+#select @@secure_file_priv;
--error 1238
set @@secure_file_priv= 0;
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index e929b4b39cc..2eb086cace5 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2439,6 +2439,37 @@ UPDATE t1 SET id=NULL;
DROP TRIGGER t1_bu;
DROP TABLE t1,t2;
+--echo #
+--echo # Bug#50755: Crash if stored routine def contains version comments
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE DATABASE db1;
+USE db1;
+
+CREATE TABLE t1 (b INT);
+CREATE TABLE t2 (a INT);
+
+CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1);
+--echo # Used to crash
+SHOW TRIGGERS IN db1;
+--error ER_PARSE_ERROR
+INSERT INTO t2 VALUES (1);
+SELECT * FROM t1;
+
+--echo # Work around Bug#45235
+let $MYSQLD_DATADIR = `select @@datadir`;
+--remove_file $MYSQLD_DATADIR/db1/t2.TRG
+--remove_file $MYSQLD_DATADIR/db1/trg1.TRN
+
+DROP DATABASE db1;
+USE test;
+
--echo End of 5.1 tests.
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 15ac6e24b16..61febb01e93 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3192,8 +3192,7 @@ String *Item_load_file::val_str(String *str)
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
/* Read only allowed from within dir specified by secure_file_priv */
- if (opt_secure_file_priv &&
- strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
+ if (!is_secure_file_path(path))
goto err;
if (!mysql_file_stat(key_file_loadfile, path, &stat_info, MYF(0)))
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 2c90aa8fbf5..950ba55a5bd 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -7711,6 +7711,45 @@ fn_format_relative_to_data_home(char * to, const char *name,
}
+/**
+ Test a file path to determine if the path is compatible with the secure file
+ path restriction.
+
+ @param path null terminated character string
+
+ @return
+ @retval TRUE The path is secure
+ @retval FALSE The path isn't secure
+*/
+
+bool is_secure_file_path(char *path)
+{
+ char buff1[FN_REFLEN], buff2[FN_REFLEN];
+ /*
+ All paths are secure if opt_secure_file_path is 0
+ */
+ if (!opt_secure_file_priv)
+ return TRUE;
+
+ if (my_realpath(buff1, path, 0))
+ {
+ /*
+ The supplied file path might have been a file and not a directory.
+ */
+ int length= (int)dirname_length(path);
+ if (length >= FN_REFLEN)
+ return FALSE;
+ memcpy(buff2, path, length);
+ buff2[length]= '\0';
+ if (length == 0 || my_realpath(buff1, buff2, 0))
+ return FALSE;
+ }
+ convert_dirname(buff2, buff1, NullS);
+ if (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
+ return FALSE;
+ return TRUE;
+}
+
static int fix_paths(void)
{
char buff[FN_REFLEN],*pos;
@@ -7777,14 +7816,13 @@ static int fix_paths(void)
}
else
{
- convert_dirname(buff, opt_secure_file_priv, NullS);
- char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
- if (secure_file_real_path == 0 ||
- my_realpath(secure_file_real_path, buff, 0))
+ if (my_realpath(buff, opt_secure_file_priv, 0))
{
sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
return 1;
}
+ char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
+ convert_dirname(secure_file_real_path, buff, NullS);
my_free(opt_secure_file_priv, MYF(0));
opt_secure_file_priv= secure_file_real_path;
}
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 8770e273445..9a6e43e4321 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -71,6 +71,7 @@ void unlink_thd(THD *thd);
bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
void flush_thread_cache();
void refresh_status(THD *thd);
+bool is_secure_file_path(char *path);
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ;
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index fc8655ea2e7..28ed4cbdbaf 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -133,6 +133,9 @@ my_bool my_net_init(NET *net, Vio* vio)
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
net->unused= 0;
+#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+ net->skip_big_packet= FALSE;
+#endif
if (vio != 0) /* If real connection */
{
@@ -967,6 +970,7 @@ my_real_read(NET *net, size_t *complen)
{
#if defined(MYSQL_SERVER) && !defined(NO_ALARM)
if (!net->compress &&
+ net->skip_big_packet &&
!my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff))
net->error= 3; /* Successfully skiped packet */
#endif
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index dee01ee0b62..e833a540032 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -747,21 +747,12 @@ create_typelib(MEM_ROOT *mem_root, Create_field *field_def, List<String> *src)
sp_head::~sp_head()
{
+ LEX *lex;
+ sp_instr *i;
DBUG_ENTER("sp_head::~sp_head");
- destroy();
- delete m_next_cached_sp;
- if (m_thd)
- restore_thd_mem_root(m_thd);
- DBUG_VOID_RETURN;
-}
-void
-sp_head::destroy()
-{
- sp_instr *i;
- LEX *lex;
- DBUG_ENTER("sp_head::destroy");
- DBUG_PRINT("info", ("name: %s", m_name.str));
+ /* sp_head::restore_thd_mem_root() must already have been called. */
+ DBUG_ASSERT(m_thd == NULL);
for (uint ip = 0 ; (i = get_instr(ip)) ; ip++)
delete i;
@@ -772,21 +763,22 @@ sp_head::destroy()
/*
If we have non-empty LEX stack then we just came out of parser with
error. Now we should delete all auxilary LEXes and restore original
- THD::lex (In this case sp_head::restore_thd_mem_root() was not called
- too, so m_thd points to the current thread context).
- It is safe to not update LEX::ptr because further query string parsing
- and execution will be stopped anyway.
+ THD::lex. It is safe to not update LEX::ptr because further query
+ string parsing and execution will be stopped anyway.
*/
- DBUG_ASSERT(m_lex.is_empty() || m_thd);
while ((lex= (LEX *)m_lex.pop()))
{
- lex_end(m_thd->lex);
- delete m_thd->lex;
- m_thd->lex= lex;
+ THD *thd= lex->thd;
+ lex_end(thd->lex);
+ delete thd->lex;
+ thd->lex= lex;
}
my_hash_free(&m_sptabs);
my_hash_free(&m_sroutines);
+
+ delete m_next_cached_sp;
+
DBUG_VOID_RETURN;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 165f88321a9..539a2da5f8c 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -305,10 +305,6 @@ public:
virtual ~sp_head();
- /// Free memory
- void
- destroy();
-
bool
execute_trigger(THD *thd,
const LEX_STRING *db_name,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f59ffd4d42f..914ef5c919a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1917,8 +1917,7 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
else
(void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
- if (opt_secure_file_priv &&
- strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
+ if (!is_secure_file_path(path))
{
/* Write only allowed to dir or subdir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index e2d0977def7..c0081c13366 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -496,6 +496,13 @@ check_user(THD *thd, enum enum_server_command command,
}
my_ok(thd);
thd->password= test(passwd_len); // remember for error messages
+ /*
+ Allow the network layer to skip big packets. Although a malicious
+ authenticated session might use this to trick the server to read
+ big packets indefinitely, this is a previously established behavior
+ that needs to be preserved as to not break backwards compatibility.
+ */
+ thd->net.skip_big_packet= TRUE;
/* Ready to handle queries */
DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 13f85b24299..f44edfdf6fb 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2194,6 +2194,7 @@ void LEX::cleanup_lex_after_parse_error(THD *thd)
*/
if (thd->lex->sphead)
{
+ thd->lex->sphead->restore_thd_mem_root(thd);
delete thd->lex->sphead;
thd->lex->sphead= NULL;
}
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 77068f3d83b..59d30b020e8 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -394,14 +394,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_ASSERT(FALSE);
#endif
}
- else if (opt_secure_file_priv)
+ else if (!is_secure_file_path(name))
{
- if (strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
- {
- /* Read only allowed from within dir specified by secure_file_priv */
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
- DBUG_RETURN(TRUE);
- }
+ /* Read only allowed from within dir specified by secure_file_priv */
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+ DBUG_RETURN(TRUE);
}
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e8809564bce..21178f828c1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1127,8 +1127,7 @@ JOIN::optimize()
}
if (conds && const_table_map != found_const_table_map &&
- (select_options & SELECT_DESCRIBE) &&
- select_lex->master_unit() == &thd->lex->unit) // upper level SELECT
+ (select_options & SELECT_DESCRIBE))
{
conds=new Item_int((longlong) 0,1); // Always false
}