[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 Created: 2020-08-05  Updated: 2021-10-15  Resolved: 2021-10-14

Status: Closed
Project: MariaDB Server
Component/s: Character Sets, Information Schema, Views
Affects Version/s: 10.1, 10.2, 10.3, 10.4, 10.5
Fix Version/s: 10.2.41, 10.3.32, 10.4.22, 10.5.13, 10.6.5, 10.7.1

Type: Bug Priority: Major
Reporter: Elena Stepanova Assignee: Alexander Barkov
Resolution: Fixed Votes: 0
Labels: None


 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



 Comments   
Comment by Alexander Barkov [ 2021-10-11 ]

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      |
+----+---------+

Comment by Alexander Barkov [ 2021-10-11 ]

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

Comment by Alexander Barkov [ 2021-10-11 ]

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.
Comment by Alexander Barkov [ 2021-10-12 ]

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              |
+------------+--------------+-----------------+

Comment by Alexander Barkov [ 2021-10-13 ]

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.

Comment by Alexander Barkov [ 2021-10-13 ]

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.

Comment by Alexander Barkov [ 2021-10-14 ]

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

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

Thanks.

Comment by Oleksandr Byelkin [ 2021-10-14 ]

OK to push

Generated at Thu Feb 08 09:22:10 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.