diff options
author | Sergei Golubchik <serg@mariadb.org> | 2019-01-25 23:12:35 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2019-01-27 18:54:12 +0100 |
commit | 2175bfce3e9da8332f10ab0e0286dc93915533a2 (patch) | |
tree | b45ab5e6be1ed5619c229202db5139d69b3cbc23 | |
parent | 21f9037186f8a4bfb45486b9c28dd146e9df0e00 (diff) | |
download | mariadb-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.txt | 10 | ||||
-rw-r--r-- | client/mysqltest.cc | 2 | ||||
-rw-r--r-- | cmake/build_configurations/mysql_release.cmake | 1 | ||||
-rw-r--r-- | config.h.cmake | 6 | ||||
-rw-r--r-- | include/mysql.h | 2 | ||||
-rw-r--r-- | include/mysql.h.pp | 2 | ||||
-rw-r--r-- | mysql-test/r/mysql.result | 26 | ||||
-rw-r--r-- | mysql-test/t/mysql.test | 22 | ||||
-rw-r--r-- | sql-common/client.c | 30 |
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); |