Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-23408

Wrong result upon query from I_S and further Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed with certain connection charset

Details

    Description

      CREATE TABLE t (a INT);
      SET SESSION character_set_connection= utf16le;
      CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
      SELECT * FROM v;
      LOCK TABLE t WRITE;
       
      # Cleanup
      DROP TABLE t;
      

      The result of SELECT * FROM v is already wrong, it returns the data for table t:

      10.3 b3e9798f

      TABLE_CATALOG	TABLE_SCHEMA	TABLE_NAME	TABLE_TYPE	ENGINE	VERSION	ROW_FORMAT	TABLE_ROWS	AVG_ROW_LENGTH	DATA_LENGTH	MAX_DATA_LENGTH	INDEX_LENGTH	DATA_FREE	AUTO_INCREMENT	CREATE_TIME	UPDATE_TIME	CHECK_TIME	TABLE_COLLATION	CHECKSUM	CREATE_OPTIONS	TABLE_COMMENT	MAX_INDEX_LENGTH	TEMPORARY
      def	test	t1	BASE TABLE	MyISAM	10	Fixed	0	0	0	1970324836974591	1024	0	NULL	2020-08-05 15:09:36	2020-08-05 15:09:36	NULL	latin1_swedish_ci	NULL			17179868160	N
      

      The wrong result is reproducible on 10.1-10.5, debug and non-debug alike.

      On 10.3+ debug builds, further LOCK causes the assertion failure:

      10.3 b3e9798f

      mysqld: /data/src/10.3/sql/table.h:2082: void TABLE_LIST::init_one_table(const LEX_CSTRING*, const LEX_CSTRING*, const LEX_CSTRING*, thr_lock_type): Assertion `!alias_arg || strlen(alias_arg->str) == alias_arg->length' failed.
      200805 15:09:36 [ERROR] mysqld got signal 6 ;
       
      #7  0x00007ffacb9b3f12 in __GI___assert_fail (assertion=0x557143ef7650 "!alias_arg || strlen(alias_arg->str) == alias_arg->length", file=0x557143ef75de "/data/src/10.3/sql/table.h", line=2082, function=0x557143efa000 <TABLE_LIST::init_one_table(st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, thr_lock_type)::__PRETTY_FUNCTION__> "void TABLE_LIST::init_one_table(const LEX_CSTRING*, const LEX_CSTRING*, const LEX_CSTRING*, thr_lock_type)") at assert.c:101
      #8  0x00005571431d5820 in TABLE_LIST::init_one_table (this=0x7ffab4071df8, db_arg=0x7ffac5bb1c20, table_name_arg=0x7ffac5bb1c30, alias_arg=0x7ffac5bb1c40, lock_type_arg=TL_WRITE) at /data/src/10.3/sql/table.h:2082
      #9  0x0000557143217751 in Locked_tables_list::init_locked_tables (this=0x7ffab4004800, thd=0x7ffab4000af0) at /data/src/10.3/sql/sql_base.cc:2210
      #10 0x00005571432abbe7 in lock_tables_open_and_lock_tables (thd=0x7ffab4000af0, tables=0x7ffab40128f0) at /data/src/10.3/sql/sql_parse.cc:2919
      #11 0x00005571432b2798 in mysql_execute_command (thd=0x7ffab4000af0) at /data/src/10.3/sql/sql_parse.cc:4941
      #12 0x00005571432bc40d in mysql_parse (thd=0x7ffab4000af0, rawbuf=0x7ffab4012818 "LOCK TABLE t WRITE", length=18, parser_state=0x7ffac5bb25e0, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:7810
      #13 0x00005571432a8c54 in dispatch_command (command=COM_QUERY, thd=0x7ffab4000af0, packet=0x7ffab41234d1 "LOCK TABLE t WRITE", packet_length=18, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1848
      #14 0x00005571432a756c in do_command (thd=0x7ffab4000af0) at /data/src/10.3/sql/sql_parse.cc:1393
      #15 0x0000557143420d5d in do_handle_one_connection (connect=0x557146dad380) at /data/src/10.3/sql/sql_connect.cc:1403
      #16 0x0000557143420abf in handle_one_connection (arg=0x557146dad380) at /data/src/10.3/sql/sql_connect.cc:1308
      #17 0x0000557143dd970c in pfs_spawn_thread (arg=0x557146dc8430) at /data/src/10.3/storage/perfschema/pfs.cc:1869
      #18 0x00007ffacd93c4a4 in start_thread (arg=0x7ffac5bb3700) at pthread_create.c:456
      #19 0x00007ffacba70d0f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97
      

      Attachments

        Activity

          bar Alexander Barkov added a comment - - edited

          Related problem:

          DROP VIEW IF EXISTS v1;
          SET NAMES utf8;
          SET SESSION character_set_connection=latin1;
          CREATE VIEW v1 AS SELECT 'ä' AS c1;
          SELECT c1, HEX(c1) FROM v1;
          

          +----+---------+
          | c1 | hex(c1) |
          +----+---------+
          | ?  | 3F      |
          +----+---------+
          

          The expected result would be:

          +----+---------+
          | c1 | hex(c1) |
          +----+---------+
          | ä  | E4      |
          +----+---------+
          

          bar Alexander Barkov added a comment - - edited Related problem: DROP VIEW IF EXISTS v1; SET NAMES utf8; SET SESSION character_set_connection=latin1; CREATE VIEW v1 AS SELECT 'ä' AS c1; SELECT c1, HEX(c1) FROM v1; +----+---------+ | c1 | hex(c1) | +----+---------+ | ? | 3F | +----+---------+ The expected result would be: +----+---------+ | c1 | hex(c1) | +----+---------+ | ä | E4 | +----+---------+
          bar Alexander Barkov added a comment - - edited

          The same crash happens with this script (without VIEWs):

          DROP TABLE IF EXISTS t;
          CREATE TABLE t (a INT);
          SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= CONCAT('t',0x00,'1');
          LOCK TABLE t WRITE;
          

          Before the crash, the SELECT returns a wrong record:

             TABLE_CATALOG: def
              TABLE_SCHEMA: test
                TABLE_NAME: t 1                 <<< --- This is wrong
                TABLE_TYPE: BASE TABLE
                    ENGINE: InnoDB
                   VERSION: 10
                ROW_FORMAT: Dynamic
                TABLE_ROWS: 0
            AVG_ROW_LENGTH: 0
               DATA_LENGTH: 16384
           MAX_DATA_LENGTH: 0
              INDEX_LENGTH: 0
                 DATA_FREE: 0
            AUTO_INCREMENT: NULL
               CREATE_TIME: 2021-10-11 16:42:45
               UPDATE_TIME: NULL
                CHECK_TIME: NULL
           TABLE_COLLATION: latin1_swedish_ci
                  CHECKSUM: NULL
            CREATE_OPTIONS: 
             TABLE_COMMENT: 
          MAX_INDEX_LENGTH: 0
                 TEMPORARY: N
          

          bar Alexander Barkov added a comment - - edited The same crash happens with this script (without VIEWs): DROP TABLE IF EXISTS t; CREATE TABLE t (a INT ); SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= CONCAT( 't' ,0x00, '1' ); LOCK TABLE t WRITE; Before the crash, the SELECT returns a wrong record: TABLE_CATALOG: def TABLE_SCHEMA: test TABLE_NAME: t 1 <<< --- This is wrong TABLE_TYPE: BASE TABLE ENGINE: InnoDB VERSION: 10 ROW_FORMAT: Dynamic TABLE_ROWS: 0 AVG_ROW_LENGTH: 0 DATA_LENGTH: 16384 MAX_DATA_LENGTH: 0 INDEX_LENGTH: 0 DATA_FREE: 0 AUTO_INCREMENT: NULL CREATE_TIME: 2021-10-11 16:42:45 UPDATE_TIME: NULL CHECK_TIME: NULL TABLE_COLLATION: latin1_swedish_ci CHECKSUM: NULL CREATE_OPTIONS: TABLE_COMMENT: MAX_INDEX_LENGTH: 0 TEMPORARY: N

          Similar to the above, but without LOCK:

          DROP TABLE IF EXISTS t;
          CREATE TABLE t (a INT);
          SELECT TABLE_NAME, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= CONCAT('t',0x00,'1');
          

          +------------+-----------------+
          | TABLE_NAME | HEX(TABLE_NAME) |
          +------------+-----------------+
          | t 1        | 740031          |
          +------------+-----------------+
          

          The result looks wrong

          • The expected result would be empty set, because there is no such table, with 0x00 in the middle of the name. So WHERE did not work fine.
          • The table name was copied from the WHERE condition into the SELECT sublist. This also looks wrong.
          bar Alexander Barkov added a comment - Similar to the above, but without LOCK: DROP TABLE IF EXISTS t; CREATE TABLE t (a INT ); SELECT TABLE_NAME, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= CONCAT( 't' ,0x00, '1' ); +------------+-----------------+ | TABLE_NAME | HEX(TABLE_NAME) | +------------+-----------------+ | t 1 | 740031 | +------------+-----------------+ The result looks wrong The expected result would be empty set, because there is no such table, with 0x00 in the middle of the name. So WHERE did not work fine. The table name was copied from the WHERE condition into the SELECT sublist. This also looks wrong.

          The same problem is repeatable with a condition on TABLE_SCHEMA:

          USE test;
          DROP TABLE IF EXISTS t;
          CREATE TABLE t (a INT);
          SELECT TABLE_NAME, TABLE_SCHEMA, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= CONCAT('test',0x00,'1');
          

          +------------+--------------+-----------------+
          | TABLE_NAME | TABLE_SCHEMA | HEX(TABLE_NAME) |
          +------------+--------------+-----------------+
          | t          | test 1       | 74              |
          +------------+--------------+-----------------+
          

          bar Alexander Barkov added a comment - The same problem is repeatable with a condition on TABLE_SCHEMA: USE test; DROP TABLE IF EXISTS t; CREATE TABLE t (a INT ); SELECT TABLE_NAME, TABLE_SCHEMA, HEX(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= CONCAT( 'test' ,0x00, '1' ); +------------+--------------+-----------------+ | TABLE_NAME | TABLE_SCHEMA | HEX(TABLE_NAME) | +------------+--------------+-----------------+ | t | test 1 | 74 | +------------+--------------+-----------------+
          bar Alexander Barkov added a comment - - edited

          Related problem:

          SET NAMES utf8;
          SET SESSION character_set_connection=latin1;
          DROP PROCEDURE IF EXISTS p1;
          DELIMITER $$
          CREATE PROCEDURE p1()
          BEGIN
            DECLARE a VARCHAR(10) CHARACTER SET utf8;
            SET a='ä';
          END;
          $$
          DELIMITER ;
          SHOW PROCEDURE CODE p1;
          

          +-----+--------------+
          | Pos | Instruction  |
          +-----+--------------+
          |   0 | set a@0 NULL |
          |   1 | set a@0 '�'   |
          +-----+--------------+
          

          Notice, the set value is not readable.

          If I further run:

          SET NAMES latin1;
          SHOW PROCEDURE CODE p1;
          

          +-----+--------------+
          | Pos | Instruction  |
          +-----+--------------+
          |   0 | set a@0 NULL |
          |   1 | set a@0 '?'  |
          +-----+--------------+
          

          the set value is still unreadable.

          bar Alexander Barkov added a comment - - edited Related problem: SET NAMES utf8; SET SESSION character_set_connection=latin1; DROP PROCEDURE IF EXISTS p1; DELIMITER $$ CREATE PROCEDURE p1() BEGIN DECLARE a VARCHAR (10) CHARACTER SET utf8; SET a= 'ä' ; END ; $$ DELIMITER ; SHOW PROCEDURE CODE p1; +-----+--------------+ | Pos | Instruction | +-----+--------------+ | 0 | set a@0 NULL | | 1 | set a@0 '�' | +-----+--------------+ Notice, the set value is not readable. If I further run: SET NAMES latin1; SHOW PROCEDURE CODE p1; +-----+--------------+ | Pos | Instruction | +-----+--------------+ | 0 | set a@0 NULL | | 1 | set a@0 '?' | +-----+--------------+ the set value is still unreadable.

          sanja, can you please review a fix:

          https://github.com/MariaDB/server/commit/901722d7d1fc021197f5f735fbde1c263b6f9028

          Note, the patch is for 10.3 to make sure it does not crash after the fix.

          10.2 did not crash. It only returned wrong result sets.

          But the patch should be pushed starting from 10.2.

          bar Alexander Barkov added a comment - sanja , can you please review a fix: https://github.com/MariaDB/server/commit/901722d7d1fc021197f5f735fbde1c263b6f9028 Note, the patch is for 10.3 to make sure it does not crash after the fix. 10.2 did not crash. It only returned wrong result sets. But the patch should be pushed starting from 10.2.

          sanja, please review a new patch version, now using check_table_name():

          https://github.com/MariaDB/server/commit/9789cbef195439a5c1a2351854becae3fd89324f

          Thanks.

          bar Alexander Barkov added a comment - sanja , please review a new patch version, now using check_table_name(): https://github.com/MariaDB/server/commit/9789cbef195439a5c1a2351854becae3fd89324f Thanks.

          OK to push

          sanja Oleksandr Byelkin added a comment - OK to push

          People

            bar Alexander Barkov
            elenst Elena Stepanova
            Votes:
            0 Vote for this issue
            Watchers:
            3 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.