Uploaded image for project: 'MariaDB Connector/C'
  1. MariaDB Connector/C
  2. CONC-525

Incorrect handling of the statement LOAD DATA LOCAL INFILE by implementation of libmariadb

Details

    • Bug
    • Status: Closed (View Workflow)
    • Critical
    • Resolution: Fixed
    • None
    • 3.2.0
    • Security
    • 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

          Activity

            Transition Time In Source Status Execution Times
            Georg Richter made transition -
            Open Closed
            15d 1h 55m 1

            People

              georg Georg Richter
              shulga Dmitry Shulga
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.