Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
None
-
None
Description
The following test case reproduces the bug:
$ cat /tmp/test_load_file
|
100
|
200
|
300
|
|
$ cat mysql-test/main/ps_load.test
|
CREATE TABLE t1 (a INT);
|
LOAD DATA LOCAL INFILE '/tmp/test_load_file' INTO TABLE t1;
|
SELECT * FROM t1;
|
DROP TABLE t1;
|
If this test case is run by mtr with the --ps-protocol option it fails
main.ps_load [ fail ]
|
Test ended at 2021-02-07 22:18:19
|
|
CURRENT_TEST: main.ps_load
|
mysqltest: At line 2: query 'LOAD DATA LOCAL INFILE '/tmp/test_load_file' INTO TABLE t1' failed: 2000: Load data local infile forbidden
|
The above listed error message is produced by libmariadb, specifically by the function mysql_handle_local_infile() that is called by mthd_my_read_query_result. Calling trace to invocation point is below:
main()
|
run_query()
|
run_query_stmt()
|
wrap_mysql_stmt_execute()
|
mysql_stmt_execute()
|
stmt_read_execute_response()
|
mthd_my_read_query_result()
|
mysql_handle_local_infile()
|
At the place of calling the function my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden") in the function mysql_handle_local_infile(), the data member conn->options.client_flag == CLIENT_LOCAL_FILES and the parameter can_local_file has the value false.
One level higher in the call stack the data member mysql->extension->auto_local_infile
has the value WAIT_FOR_QUERY, the expression
my_bool can_local_infile= (mysql->options.extension) &&(mysql->extension->auto_local_infile != WAIT_FOR_QUERY);
|
has the value false, as a consequences the argument value for the parameter can_local_file of the function mysql_handle_local_infile() also has the value false.
In case the original test case is run by mtr WITHOUT the option --ps-protocol, the parameter can_local_file of the function mysql_handle_local_infile() has the value true since the data member mysql->extension->auto_local_infile has the value ACCEPT_FILE_REQUEST.
The value ACCEPT_FILE_REQUEST is assigned to the the data member mysql->extension->auto_local_infile inside the function ma_simple_command:
int
|
ma_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, |
size_t length, my_bool skipp_check, void *opt_arg) |
{
|
if ((mysql->options.client_flag & CLIENT_LOCAL_FILES) && |
mysql->options.extension && mysql->extension->auto_local_infile == WAIT_FOR_QUERY &&
|
arg && (*arg == 'l' || *arg == 'L') && |
command == COM_QUERY)
|
{
|
if (strncasecmp(arg, "load", 4) == 0) |
mysql->extension->auto_local_infile= ACCEPT_FILE_REQUEST; <<===== This is that place
|
}
|
return mysql->methods->db_command(mysql, command, arg, length, skipp_check, opt_arg); |
}
|
If the following modification be applied to the source code of the library libmariadb
--- a/libmariadb/mariadb_stmt.c
|
+++ b/libmariadb/mariadb_stmt.c
|
@@ -1713,6 +1713,17 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon
|
}
|
memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count);
|
}
|
+ if ((mysql->options.client_flag & CLIENT_LOCAL_FILES) &&
|
+ mysql->options.extension && mysql->extension->auto_local_infile == WAIT_FOR_QUERY &&
|
+ (query[0] == 'l' || query[0] == 'L'))
|
+ {
|
+ if (strncasecmp(query, "load", 4) == 0)
|
+ mysql->extension->auto_local_infile= ACCEPT_FILE_REQUEST;
|
+ } |
then the original failure of the test main.ps_load when it is run with the option --ps-protocol be fixed.
The proposed changes in the source code of the function mysql_stmt_prepare() is obviously just a hack to temporarily fix the issue.
So, the major question is what was the reason to write so non-obvious and pretty hacked implementation for handling of statement LOAD DATA LOCAL INFILE on client side?
Attachments
Issue Links
- relates to
-
CONC-515 Implement safe LOAD DATA LOCAL INFILE method
- Stalled