summaryrefslogtreecommitdiff
path: root/sql-common
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 /sql-common
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.
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/client.c30
1 files changed, 27 insertions, 3 deletions
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);