summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2019-01-25 23:12:35 +0100
committerSergei Golubchik <serg@mariadb.org>2019-01-27 18:54:12 +0100
commit2175bfce3e9da8332f10ab0e0286dc93915533a2 (patch)
treeb45ab5e6be1ed5619c229202db5139d69b3cbc23
parent21f9037186f8a4bfb45486b9c28dd146e9df0e00 (diff)
downloadmariadb-git-2175bfce3e9da8332f10ab0e0286dc93915533a2.tar.gz
Crude "auto-load-data-local-infile" modemariadb-5.5.63
Disable LOAD DATA LOCAL INFILE suport by default and auto-enable it for the duration of one query, if the query string starts with the word "load". In all other cases the application should enable LOAD DATA LOCAL INFILE support explicitly.
-rw-r--r--CMakeLists.txt10
-rw-r--r--client/mysqltest.cc2
-rw-r--r--cmake/build_configurations/mysql_release.cmake1
-rw-r--r--config.h.cmake6
-rw-r--r--include/mysql.h2
-rw-r--r--include/mysql.h.pp2
-rw-r--r--mysql-test/r/mysql.result26
-rw-r--r--mysql-test/t/mysql.test22
-rw-r--r--sql-common/client.c30
9 files changed, 90 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b15512683fa..bc4c4e4f103 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -256,9 +256,15 @@ IF(HAVE_GGDB3)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
ENDIF()
-OPTION(ENABLED_LOCAL_INFILE
- "If we should should enable LOAD DATA LOCAL by default" ${IF_WIN})
+SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)")
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
+IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$")
+ SET(ENABLED_LOCAL_INFILE OFF)
+ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$")
+ SET(ENABLED_LOCAL_INFILE ON)
+ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$")
+ MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO")
+ENDIF()
OPTION(WITH_FAST_MUTEXES "Compile with fast mutexes" OFF)
MARK_AS_ADVANCED(WITH_FAST_MUTEXES)
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 2b7401878ef..842bde3b99e 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -6045,7 +6045,6 @@ void do_connect(struct st_command *command)
#endif
if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
- mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
@@ -9110,7 +9109,6 @@ int main(int argc, char **argv)
(void *) &opt_connect_timeout);
if (opt_compress)
mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS);
- mysql_options(con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
mysql_options(con->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index 39ad0e68d35..a464631e9a2 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -94,7 +94,6 @@ IF(FEATURE_SET)
ENDFOREACH()
ENDIF()
-OPTION(ENABLED_LOCAL_INFILE "" ON)
IF(RPM)
SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "")
diff --git a/config.h.cmake b/config.h.cmake
index 99a2ebdd093..271d77f2e5a 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -530,7 +530,11 @@
/*
MySQL features
*/
-#cmakedefine ENABLED_LOCAL_INFILE 1
+#define LOCAL_INFILE_MODE_OFF 0
+#define LOCAL_INFILE_MODE_ON 1
+#define LOCAL_INFILE_MODE_AUTO 2
+#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_@ENABLED_LOCAL_INFILE@
+
#cmakedefine ENABLED_PROFILING 1
#cmakedefine EXTRA_DEBUG 1
#cmakedefine BACKUP_TEST 1
diff --git a/include/mysql.h b/include/mysql.h
index 2f205ec6463..1ed6ffe67c8 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -274,7 +274,7 @@ typedef struct st_mysql
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
- my_bool unused1;
+ my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 4f7407095c9..8bff18d7bb0 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -341,7 +341,7 @@ typedef struct st_mysql
my_bool free_me;
my_bool reconnect;
char scramble[20 +1];
- my_bool unused1;
+ my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts;
const struct st_mysql_methods *methods;
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index 8a24128daa2..ffa5d020153 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -587,3 +587,29 @@ a
2
drop table "a1\""b1";
set sql_mode=default;
+create table t1 (a text);
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+drop table t1;
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 87756768c7f..f526a3fea91 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -656,3 +656,25 @@ show create table "a1\""b1";
select * from "a1\""b1";
drop table "a1\""b1";
set sql_mode=default;
+
+#
+# mysql --local-infile
+#
+--let $ldli = load data local infile '$MYSQLTEST_VARDIR/tmp/bug.sql' into table test.t1;
+create table t1 (a text);
+--exec $MYSQL -e "$ldli"
+select count(*) from t1; truncate table t1;
+--exec $MYSQL --enable-local-infile -e "$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL --disable-local-infile -e "$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+--exec $MYSQL --enable-local-infile -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL --disable-local-infile -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+drop table t1;
diff --git a/sql-common/client.c b/sql-common/client.c
index 952b6a199ee..bec778e7d51 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -115,6 +115,12 @@ my_bool net_flush(NET *net);
#include <my_context.h>
#include <mysql_async.h>
+typedef enum {
+ ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */
+ WAIT_FOR_QUERY, /* heuristics is enabled, not sending files */
+ ACCEPT_FILE_REQUEST /* heuristics is enabled, ready to send a file */
+} auto_local_infile_state;
+
#define native_password_plugin_name "mysql_native_password"
#define old_password_plugin_name "mysql_old_password"
@@ -1765,8 +1771,10 @@ mysql_init(MYSQL *mysql)
--enable-local-infile
*/
-#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)
+#if ENABLED_LOCAL_INFILE && !defined(MYSQL_SERVER)
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
+ mysql->auto_local_infile= ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
#endif
#ifdef HAVE_SMEM
@@ -3951,8 +3959,14 @@ static my_bool cli_read_query_result(MYSQL *mysql)
ulong field_count;
MYSQL_DATA *fields;
ulong length;
+#ifdef MYSQL_CLIENT
+ my_bool can_local_infile= mysql->auto_local_infile != WAIT_FOR_QUERY;
+#endif
DBUG_ENTER("cli_read_query_result");
+ if (mysql->auto_local_infile == ACCEPT_FILE_REQUEST)
+ mysql->auto_local_infile= WAIT_FOR_QUERY;
+
if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
@@ -3989,7 +4003,8 @@ get_info:
{
int error;
- if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES))
+ if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES) ||
+ !can_local_infile)
{
set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
DBUG_RETURN(1);
@@ -4027,6 +4042,13 @@ int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{
DBUG_ENTER("mysql_send_query");
+ if (mysql->options.client_flag & CLIENT_LOCAL_FILES &&
+ mysql->auto_local_infile == WAIT_FOR_QUERY &&
+ (*query == 'l' || *query == 'L'))
+ {
+ if (strncasecmp(query, STRING_WITH_LEN("load")) == 0)
+ mysql->auto_local_infile= ACCEPT_FILE_REQUEST;
+ }
DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
}
@@ -4241,10 +4263,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
break;
case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
- if (!arg || test(*(uint*) arg))
+ if (!arg || *(uint*) arg)
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
else
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
+ mysql->auto_local_infile= arg && *(uint*)arg == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
break;
case MYSQL_INIT_COMMAND:
add_init_command(&mysql->options,arg);